MinioAsyncClient#uploadSnowballObjects may close RandomAccessFile before asynchronous upload completes when using stagingFilename #1718
Description
SDK Version
minio-java 9.0.3
Description
When stagingFilename is used, uploadSnowballObjects() opens the generated TAR file with RandomAccessFile inside a try-with-resources block:
try (RandomAccessFile file = new RandomAccessFile(args.stagingFilename(), "r")) {
return putObject(new PutObjectAPIArgs(args, file, length, headers));
}
However, putObject() returns a CompletableFuture, and the HTTP request is executed asynchronously.
This means the RandomAccessFile may be closed immediately after putObject() returns, while the HTTP request is still reading from it.
Potential sequence:
open `RandomAccessFile`
↓
`putObject()` enqueues async HTTP request
↓
` putObject()` returns `CompletableFuture`
↓
try-with-resources closes `RandomAccessFile`
↓
HTTP request tries to read from the closed file
Reproduction
MinioClient client =
MinioClient.builder()
.credentials("minio", "Minio@123")
.endpoint("http://192.168.1.10:9000")
.build();
client
.uploadSnowballObjects(
UploadSnowballObjectsArgs
.builder()
.bucket("migration")
.objects(
List.of(
new SnowballObject("test/test.docx", "/tmp/output.docx")
)
)
.stagingFilename("/tmp/test.tar")
.build()
);
Result
The upload may fail while OkHttp is reading the request body because the underlying RandomAccessFile has already been closed.
For example, an exception similar to the following may occur:
Exception in thread "main" io.minio.errors.MinioException: java.io.IOException: Stream Closed
at io.minio.Http$RequestBody.<init>(Http.java:1046)
at io.minio.Http$Body.toRequestBody(Http.java:994)
at io.minio.Http$S3Request.toRequest(Http.java:1798)
at io.minio.Http$S3Request.toRequest(Http.java:1859)
at io.minio.BaseS3Client.executeAsync(BaseS3Client.java:345)
at io.minio.BaseS3Client.lambda$executeAsync$1(BaseS3Client.java:519)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
at io.minio.BaseS3Client$1.onResponse(BaseS3Client.java:381)
at io.minio.BaseS3Client$1.onResponse(BaseS3Client.java:367)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: java.io.IOException: Stream Closed
at java.base/java.io.RandomAccessFile.getFilePointer(Native Method)
at io.minio.Http$RequestBody.<init>(Http.java:1044)
Expected Behavior
The RandomAccessFile should remain open until the asynchronous upload completes.
Could you please confirm whether this is a resource lifecycle issue in MinioAsyncClient#uploadSnowballObjects()?
Activity
balamurugana commentedon Sep 15, 2026
Fixed by #1711