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>

FilterExpression 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 ValidationExceptionclient-side and not retryable until you restructure.

Why it happens

  • A key condition written as a filterFilterExpression: 'sk = :v' where sk is the sort key; it belongs in KeyConditionExpression.
  • Filtering on the index's key — when you Query a 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

  1. Move key conditions into KeyConditionExpression:
    KeyConditionExpression: 'pk = :pk AND begins_with(sk, :prefix)',
    // FilterExpression: only NON-key attributes, e.g. 'status = :active'
  2. 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.
  3. 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.
  4. Querying a GSI? Remember its key attributes are off-limits in the filter too — condition on them in the key condition.

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.