Attribute name is a reserved keyword

TL;DR — You used an attribute name that's one of DynamoDB's reserved words (there are ~570 — status, name, size, type, data, year, count, and many more) directly in an expression. Replace it with an ExpressionAttributeNames placeholder — #status mapped to status — and the request goes through.

What it means

ValidationException: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: status
ValidationException: Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: name

DynamoDB keeps a list of reserved words that can't appear literally in an expression (UpdateExpression, ConditionExpression, FilterExpression, KeyConditionExpression, ProjectionExpression). When your attribute happens to be one of them, the parser rejects the expression. It's a ValidationException (HTTP 400), not retryable until you alias the name. The message names the exact reserved word.

Why it happens

  • A common attribute name collides with a reserved wordstatus, name, size, type, data, year, count, timestamp, source, region, and hundreds more are reserved.
  • A ProjectionExpression that lists a reserved attribute name directly.
  • A FilterExpression/ConditionExpression referencing a reserved name (#status = :s works; status = :s doesn't).
  • An attribute name that starts with a number, or contains a space or dot — these also require an ExpressionAttributeNames alias, and produce a related validation error.

How to fix it

  1. Alias the name with ExpressionAttributeNames. Map a #placeholder to the real name and use the placeholder in the expression:
    await doc.send(
      new UpdateCommand({
        TableName: 'Orders',
        Key: {pk: 'ORDER#1'},
        UpdateExpression: 'SET #status = :s',
        ExpressionAttributeNames: {'#status': 'status'},
        ExpressionAttributeValues: {':s': 'shipped'}
      })
    );
  2. A placeholder must start with # followed by alphanumerics/underscore, and every #name used must be defined (and every defined one used).
  3. Alias defensively — aliasing every attribute name in your expressions avoids ever having to know which words are reserved.
  4. Alias names with a dot too — #addr.#city where the dot is a literal part of the name (otherwise DynamoDB reads . as a document-path separator).

FAQ

How do I fix "Attribute name is a reserved keyword" in DynamoDB? Alias the attribute with ExpressionAttributeNames. Map a placeholder such as #status to the real name "status" and use #status in the expression instead of the literal word. The placeholder must start with # and every one you define must be used.

Which DynamoDB attribute names are reserved? There are around 570 reserved words, including everyday names like status, name, size, type, data, year, count, timestamp, and region. Rather than memorize the list, alias every attribute name in your expressions with ExpressionAttributeNames.

Mit DynamoDB ohne die Console arbeiten

DynoTable ist ein schneller Desktop-Client für DynamoDB — durchsuche Tabellen, führe SQL-artige Queries aus und bearbeite Items lokal.