Filter Expression can only contain non-primary key attributes
TL;DR — You put a primary key attribute (partition key or sort key — of the table or the index you're querying) inside a FilterExpression. DynamoDB forbids that: key attributes go in the KeyConditionExpression, and a filter can only reference non-key attributes. Move the key condition where it belongs.
What it means
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: pkFilterExpression runs after items are read, to discard rows you don't want; KeyConditionExpression runs before, to select which items are read by key. Referencing a partition/sort key in the filter mixes those roles, so DynamoDB rejects it with an HTTP 400 ValidationException — client-side and not retryable until you restructure.
Why it happens
- A key condition written as a filter —
FilterExpression: 'sk = :v'whereskis the sort key; it belongs inKeyConditionExpression. - Filtering on the index's key — when you
Querya GSI/LSI, that index's own partition/sort key are "primary key attributes" for this query and can't appear in the filter. - Copy-pasting a scan filter onto a query where one filtered attribute happens to be a key.
- Trying to add a second condition on the sort key via the filter (e.g. a range) instead of expressing it in the key condition.
How to fix it
- Move key conditions into
KeyConditionExpression:KeyConditionExpression: 'pk = :pk AND begins_with(sk, :prefix)', // FilterExpression: only NON-key attributes, e.g. 'status = :active' - Use the right index. If you need to filter/select on an attribute that isn't a key, model it as the partition/sort key of a GSI and query that index by key.
- Keep the filter for non-key attributes only — it trims results but still consumes read capacity for every item scanned, so lean on keys/indexes for selection.
- Querying a GSI? Remember its key attributes are off-limits in the filter too — condition on them in the key condition.
- Audit generated requests. Log both
KeyConditionExpressionandFilterExpressiontogether — key attributes in the filter are a common copy-paste mistake from Scan code.
Run it in DynoTable
DynoTable's query panel keeps key conditions and filters in separate fields — partition and sort key constraints never land in FilterExpression. Open a table with ⌘K, set the key condition, then add non-key filters; copy the generated request into your SDK.
Use the Query Builder to prototype GSI queries where index keys must stay in KeyConditionExpression. Switch profiles with ⌘P; Test Connection on Settings → Profiles confirms the index exists. See Connect to AWS and Install.
Sources
- Query — Amazon DynamoDB API Reference (verified 2026-07-13)
- Filter expressions for Query (verified 2026-07-13)
Related errors
- Query key condition not supported — an invalid operator/shape in the key condition itself.
- Query condition missed key schema element — the query didn't supply the partition key.
- Code example: Query in Node.js — key condition and filter split correctly.
- Learn: Filtering strategies · Key condition expressions
References
- Query — Amazon DynamoDB API Reference
- Filter expressions for Query — Amazon DynamoDB Developer Guide
- Using Global Secondary Indexes in DynamoDB — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.