Skip to content

ScanCommand with no Limit set only ever reads one page of data  #6043

@mn-prp

Description

@mn-prp

Checkboxes for prior research

Describe the bug

Using ScanCommand without a Limit results in only one page of data being read and no LastEvaluatedKey being returned to resume at the next page. The documentation clearly suggests that if the 1mb page limit is hit, we should get a LastEvaluatedKey in the response.

I am (now) aware that this functionality can be achieved using paginateScan, but I think it is still a bug in ScanCommand as a standalone.

SDK version number

@aws-sdk/lib-dynamodb@npm:3.565.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

Node v20.12.0

Reproduction Steps

Here is what I wrote. Note from my comment below that adding or removing the Limit changes the behavior of this code, even though I do not expect it to.

const scanFrom = (lastEvaluatedKey?: Record<string, any>) =>
      client.send(
        new ScanCommand({
          TableName: this.tableName,
          FilterExpression: 'begins_with(sk, :sk)',
          ExpressionAttributeValues: {
            ':sk': sk
          },
          ExclusiveStartKey: lastEvaluatedKey,
          // Limit: 1000 <-- if we uncomment this line, and set it to anything other than 0 or undefined, it works, otherwise only one page of data returned with no ExclusiveStartKey
        })
      )

    let results: ScanCommandOutput['Items'] = []

    let page = await scanFrom(undefined)

    while (page.LastEvaluatedKey !== undefined) {
      results = results.concat(page.Items ?? [])
      page = await scanFrom(page.LastEvaluatedKey)
    }

    return results

Observed Behavior

As my comment indicates, adding or removing the Limit changes the behavior such that either a LastEvaluatedKey is returned or not, and if Limit is missing, we always only get one page of data (not the complete scan results after paginating).

Expected Behavior

This is the behavior I was trying to achieve (i.e., get everything from the table matching the filter expression), but using the raw ScanCommand instead:

    const paginator = paginateScan(
      { client },
      {
        TableName: this.tableName,
        FilterExpression: 'begins_with(sk, :sk)',
        ExpressionAttributeValues: {
          ':sk': sk
        }
      }
    )

    let results: ScanCommandOutput['Items'] = []
    for await (const page of paginator) {
      results = results.concat(page.Items ?? [])
    }

    return results

Possible Solution

No response

Additional Information/Context

No response

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.closing-soonThis issue will automatically close in 4 days unless further comments are made.p3This is a minor priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions