-
Notifications
You must be signed in to change notification settings - Fork 634
Description
Pre-Migration Checklist
- I've read the Migration Guide.
- I've reviewed the upgrading notes and major version differences mentioned in
UPGRADING.md
. - I've checked AWS Forums and StackOverflow for similar migration issues.
Which JavaScript Runtime is this issue in?
Node.js (includes AWS Lambda)
AWS Lambda Usage
- Yes, my application is running on AWS Lambda.
- No, my application is not running on AWS Lambda.
Describe the Migration Issue
The S3 ListObjectsV2
result is different when no objects exist for the given prefix. In v2, Contents
and CommonPrefixes
are empty arrays. In v3, these properties are not present at all in ListObjectsV2CommandOutput
, and thus evaluate to undefined
. Additionally, in v3, if Delimiter
is not passed in the input, CommonPrefixes
will be absent in the output, whereas v2 included it as an empty array.
This caused us a production outage. With v2, our code checked for Contents
being falsy, but because we could never find a scenario where that actually occurred, we considered it an unexpected error. With v3, the behavior changed unexpectedly.
In my opinion, this is a bad, or at least unconventional API design choice. In most APIs (not AWS specific), if you are searching for any number of matches and getting an array back, and the thing is not found, you get an empty array, rather than the property disappearing. An example is JavaScript's Array#filter
method.
I checked all the following documentation and did not see this important difference covered anywhere:
- https://github.com/aws/aws-sdk-js-v3/blob/main/UPGRADING.md
- https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_s3_code_examples.html
- https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/migrate-s3.html
- https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/ListObjectsV2Command/
- https://github.com/aws/aws-sdk-js-v3/blob/main/supplemental-docs/CLIENTS.md
I acknowledge that the documentation says the Contents
can be undefined
, but it does not say under what circumstances exactly that can occur. In v2, it never occurred. Since the SDK is very sloppy about what can actually be undefined
, as often things that are declared | undefined
actually never can be (and previously this was the case for this operation), it was an unexpected change.
Code Comparison
V2:
const {Contents} = await client.listObjectsV2(params).promise();
if (!Contents) {
throw new Error(
`Error getting object matching params: ${JSON.stringify(params)}`
);
}
return Contents;
V3:
const { Contents } = await client.send(new ListObjectsV2Command(params));
return Contents ?? [];
Observed Differences/Errors
Contents
is not present in the output when no objects matching the prefix exist.
Additional Context
No response