-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
I'm using TransferManager
to conditionally copy an object if it has a matching ETag. I would like to be able to identify when a transfer has failed because the constraints weren't met (as opposed to failing for some other reason), but that doesn't appear to be possible due to the way TransferManager
handles failing constraints.
I'm copying the object like this:
CopyObjectRequest copyRequest = new CopyObjectRequest(srcBucket, srcKey, destBucket, destKey);
copyRequest.setMatchingETagConstraints(Collections.singletonList(expectedETag));
s3TransferManager.copy(copyRequest).waitForCopyResult();
If the ETag doesn't match then this exception is throw:
com.amazonaws.AmazonClientException: Unable to complete transfer: null
at com.amazonaws.services.s3.transfer.internal.AbstractTransfer.unwrapExecutionException(AbstractTransfer.java:286) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at com.amazonaws.services.s3.transfer.internal.AbstractTransfer.rethrowExecutionException(AbstractTransfer.java:265) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at com.amazonaws.services.s3.transfer.internal.CopyImpl.waitForCopyResult(CopyImpl.java:67) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
<SNIP>
Caused by: java.lang.NullPointerException: null
at com.amazonaws.services.s3.transfer.internal.CopyCallable.copyInOneChunk(CopyCallable.java:154) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at com.amazonaws.services.s3.transfer.internal.CopyCallable.call(CopyCallable.java:134) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at com.amazonaws.services.s3.transfer.internal.CopyMonitor.call(CopyMonitor.java:132) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at com.amazonaws.services.s3.transfer.internal.CopyMonitor.call(CopyMonitor.java:43) ~[aws-java-sdk-s3-1.11.351.jar!/:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_111]
... 3 common frames omitted
The NullPointerException
occurs because the return value from s3.copyObject(copyObjectRequest)
(which returns null
when constraints aren't met) is not checked before calling copyObjectResult.getETag()
: https://github.com/aws/aws-sdk-java/blob/1.11.351/aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/transfer/internal/CopyCallable.java#L146-L154.
It looks like there may be other parts of the code that aren't checking nullable return values: https://github.com/aws/aws-sdk-java/blob/1.11.351/aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/transfer/internal/CopyPartCallable.java#L41
I'm not sure what the correct behaviour here should be. I was expecting a AmazonS3Exception
with the appropriate status code, but I'm not sure how you'd achieve that as AmazonS3Client
is documented to swallow these exceptions and return null. Throwing a AmazonClientException
with a message about constraints would be an improvement for debugging, but it's not a good way to programmatically detect the reason the transfer had failed.