Skip to content

MIGRATION ISSUE: S3 ListObjectsV2 returns undefined instead of empty array #7152

@vobarian

Description

@vobarian

Pre-Migration Checklist

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:

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

Metadata

Metadata

Assignees

Labels

p3This is a minor priority issuev2-v3-inconsistencyBehavior has changed from v2 to v3, or feature is missing altogether

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions