The provided starting key is invalid

TL;DR — 你的 ExclusiveStartKey 与你正在分页的对象的键模式不匹配。它必须恰好包含 DynamoDB 在 LastEvaluatedKey 中返回的键属性——完整的主键,加上你查询 GSI/LSI 时的索引键——名称和类型都相同。把 LastEvaluatedKey 原样传回;手工拼装它正是这出错的地方。

含义

ValidationException: The provided starting key is invalid
ValidationException: Exclusive Start Key must have same size as table's key schema

ExclusiveStartKey 告诉一个 Query/Scan 从哪里恢复。DynamoDB 会根据表的键模式——或者对于索引查询,LastEvaluatedKey 携带的组合索引键加表键——来验证它。缺少属性、多余属性、名称错误或类型错误都会在读取任何数据之前失败。

为什么会发生

  • 只用分区键手工构建键——一个复合键表在起始键中需要分区_和_排序键。
  • 只用表键对索引分页——GSI/LSI 查询上的 LastEvaluatedKey 同时包含索引键属性和表的主键;它们全都必须传回。
  • 类型或名称漂移——键被序列化了(JSON、URL 参数、缓存)并带着 "42" 回来,而 LastEvaluatedKey 里是一个数字,或者带着一个改了名的字段。
  • 跨查询复用键——把来自一张表/索引的 LastEvaluatedKey 传给了针对另一个的查询,或者在键模式假设改变之后传给了同一个查询。
  • 一个封装注入了默认值——一个 ODM 填入它以为属于键的属性,会把起始键撑过模式大小。

如何修复

  1. 原封不动地往返 LastEvaluatedKey

    let ExclusiveStartKey;
    do {
      const page = await docClient.send(
        new QueryCommand({
          TableName,
          KeyConditionExpression,
          ExpressionAttributeValues,
          ExclusiveStartKey
        })
      );
      items.push(...(page.Items ?? []));
      ExclusiveStartKey = page.LastEvaluatedKey; // verbatim — no rebuild
    } while (ExclusiveStartKey);
  2. 如果它跨越请求边界就无损地序列化它——当分页游标去往浏览器又回来时,编码整个 LastEvaluatedKey 对象(例如其 JSON 的 base64),而不是从项目字段重建它,并保持数字类型仍为数字。

  3. 为索引分页包含每个键属性——索引分区键/排序键_和_表分区键/排序键,与返回的完全一致。

  4. 不要捏造一个起始点——DynamoDB 分页没有偏移量;如果你需要"从 X 附近开始",就在 KeyConditionExpressionsk > :x)中表达它,而不是手工制作一个 ExclusiveStartKey

检查你的表或索引的 LastEvaluatedKey 实际包含什么,能免去猜测——DynoTable 桌面应用会翻页浏览查询并显示原始游标,而 DynamoDB Expression Builder 会围绕它组合查询请求。

相关错误

References

最后核实于 2026-07-13,依据上方链接的 AWS 官方文档。

无需控制台即可使用 DynamoDB

DynoTable 是面向 DynamoDB 的快速桌面客户端 —— 浏览表、运行 SQL 风格的查询,并在本地编辑项。