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: nameDynamoDB 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 word —
status,name,size,type,data,year,count,timestamp,source,region, and hundreds more are reserved. - A
ProjectionExpressionthat lists a reserved attribute name directly. - A
FilterExpression/ConditionExpressionreferencing a reserved name (#status = :sworks;status = :sdoesn't). - An attribute name that starts with a number, or contains a space or dot — these also require an
ExpressionAttributeNamesalias, and produce a related validation error.
How to fix it
- Alias the name with
ExpressionAttributeNames. Map a#placeholderto 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'} }) ); - A placeholder must start with
#followed by alphanumerics/underscore, and every#nameused must be defined (and every defined one used). - Alias defensively — aliasing every attribute name in your expressions avoids ever having to know which words are reserved.
- Alias names with a dot too —
#addr.#citywhere 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.
Related errors
- Invalid UpdateExpression syntax — malformed expression structure.
- ValidationException (overview)
- Learn: Expression names & values · Update expressions