Filter Expression can only contain non-primary key attributes

TL;DR — 你把一个主键属性(分区键或排序键——无论是表的还是你所查询的索引的)放进了 FilterExpression。DynamoDB 禁止这样做:键属性进 KeyConditionExpression,而过滤器只能引用非键属性。把键条件移到它该在的地方。

含义

ValidationException: Filter Expression can only contain non-primary key attributes:
Primary key attribute: <name>

# what the engine actually returns, reproduced against DynamoDB Local:
ValidationException: Filter Expression can only contain non-primary key attributes: Primary key attribute: pk

FilterExpression 在项目被读取之后运行,用来丢弃你不想要的行;KeyConditionExpression之前运行,用来按键选择读取哪些项目。在过滤器中引用分区键/排序键混淆了这些角色,因此 DynamoDB 以一个 HTTP 400 ValidationException 拒绝它——属于客户端错误,在你重构之前不可重试

为什么会发生

  • 把键条件写成了过滤器——FilterExpression: 'sk = :v',其中 sk 是排序键;它属于 KeyConditionExpression
  • 对索引的键做过滤——当你 Query 一个 GSI/LSI 时,那个索引自己的分区键/排序键对本次查询而言就是"主键属性",不能出现在过滤器中。
  • 把一个 scan 过滤器复制粘贴到一个 query 上,而其中一个被过滤的属性恰好是键。
  • 试图通过过滤器为排序键添加第二个条件(例如一个范围),而不是在键条件中表达它。

如何修复

  1. 把键条件移入 KeyConditionExpression
    KeyConditionExpression: 'pk = :pk AND begins_with(sk, :prefix)',
    // FilterExpression: only NON-key attributes, e.g. 'status = :active'
  2. 使用正确的索引。 如果你需要在一个非键属性上过滤/选择,就把它建模为某个 GSI 的分区键/排序键并按键查询那个索引。
  3. 让过滤器只用于非键属性——它会裁剪结果,但仍然会为扫描到的每个项目消耗读取容量,因此要依靠键/索引来做选择。
  4. 在查询 GSI? 记住它的键属性在过滤器里同样禁用——在键条件中对它们做条件。

在 DynoTable 中运行

DynoTable 的查询面板将关键条件和过滤器保留在单独的字段中 - 分区和排序键约束永远不会落在 FilterExpression 中。用⌘K打开一张表,设置关键条件,然后添加非关键过滤器;将生成的请求复制到你的 SDK 中。使用 Query Builder 原型 GSI 查询,其中索引键必须保留在 KeyConditionExpression 中。使用 ⌘P 切换配置文件;在“设置”→“配置文件”上Test Connection,确认索引存在。参见连接 AWS安装

来源

相关错误

参考资料

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

无需控制台即可使用 DynamoDB

一款快速的 DynamoDB 桌面客户端,可运行 DynamoDB 无法执行的真正 SQL——JOINs、GROUP BY、聚合——并支持可视化编辑和运行在你自己的 Bedrock 密钥上的 AI agent。

30 天免费试用,无需信用卡 — 之后为无时间限制的免费版。