Skip to content

[Bug] GSI pagination with duplicate index sort keys returns no items on a composite base table #238

Description

@Iamrodos

Describe the bug

A Query on a GSI whose index sort key values are duplicated returns page one plus a LastEvaluatedKey, but resuming with that same key returns zero items. Nothing errors, so a paginating client reads page one and concludes it has everything.

The base table needs a range key. TestGSIOnHashOnlyBaseTable::test_paginate_duplicate_gsi_sort_keys already covers this index shape on a hash only base table and passes; adding a range key to that fixture reproduces the failure. Same class as #145.

Reproduced on both the sqlite and the default postgres backend at aefd1b6.

To Reproduce

EP=https://localhost:18443   # or your endpoint

aws dynamodb create-table --table-name esk \
  --attribute-definitions \
      AttributeName=pk,AttributeType=S AttributeName=sk,AttributeType=S \
      AttributeName=gsipk,AttributeType=S AttributeName=gsisk,AttributeType=S \
  --key-schema AttributeName=pk,KeyType=HASH AttributeName=sk,KeyType=RANGE \
  --global-secondary-indexes '[{"IndexName":"gsi","KeySchema":[{"AttributeName":"gsipk","KeyType":"HASH"},{"AttributeName":"gsisk","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"}}]' \
  --billing-mode PAY_PER_REQUEST --endpoint-url $EP
aws dynamodb wait table-exists --table-name esk --endpoint-url $EP

# Five items sharing one index sort key value, differing only in the base keys.
for i in 1 2 3 4 5; do
  aws dynamodb put-item --table-name esk --endpoint-url $EP \
    --item "{\"pk\":{\"S\":\"item$i\"},\"sk\":{\"S\":\"S\"},\"gsipk\":{\"S\":\"P\"},\"gsisk\":{\"S\":\"DUP\"}}"
done

# Page one: Count 2, plus a LastEvaluatedKey.
aws dynamodb query --table-name esk --index-name gsi --limit 2 --endpoint-url $EP \
  --key-condition-expression "gsipk = :p" \
  --expression-attribute-values '{":p":{"S":"P"}}'

# Page two, resuming from that LastEvaluatedKey verbatim.
aws dynamodb query --table-name esk --index-name gsi --limit 2 --endpoint-url $EP \
  --key-condition-expression "gsipk = :p" \
  --expression-attribute-values '{":p":{"S":"P"}}' \
  --exclusive-start-key '{"gsipk":{"S":"P"},"gsisk":{"S":"DUP"},"pk":{"S":"item2"},"sk":{"S":"S"}}'

Expected behavior

Page two returns the remaining items, as it does for the same index shape on a hash only base table.

Actual behavior

Page two returns nothing, with no error:

{"Count": 0, "ScannedCount": 0, "Items": []}

Environment

  • ExtendDB version: 0.1.2, commit aefd1b6
  • Operating system: macOS 15 (Darwin 24.6.0)
  • Rust version (if building from source): 1.97.1
  • Client SDK/driver and version: AWS CLI v2
  • Deployment method (binary, container, source): source

Additional context

A regression test is the existing gsi_on_hash_only_base_table fixture with a range key added to its key_schema; the surrounding test body needs no change. Happy to open a PR.

DISCLAIMER: this issue was diagnosed with an LLM agent. I've reviewed and reproduced it.

Checklist

  • I have searched existing issues for duplicates
  • I have included the ExtendDB version and environment details
  • I can reproduce this on current main (aefd1b6)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions