ValidationException: Invalid UpdateExpression

TL;DR — Your UpdateExpression is malformed. Nine times out of ten it's a reserved keyword (like status, name, size) used directly — swap it for a #placeholder in ExpressionAttributeNames. The message names the exact token.

What it means

Typical messages:

ValidationException: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: status
ValidationException: Invalid UpdateExpression: Syntax error; token: "=", near: "SET status ="
ValidationException: Invalid UpdateExpression: An expression attribute value used in expression is not defined; attribute value: :s

DynamoDB parses the expression string and rejects anything that isn't valid grammar or references an undefined placeholder.

Why it happens

  • Reserved keyword used raw. DynamoDB has hundreds of reserved wordsstatus, name, size, count, data, year. Used directly in an expression they cause a syntax error.
  • Missing ExpressionAttributeNames entry for a #name you referenced.
  • Missing ExpressionAttributeValues entry for a :value you referenced.
  • Wrong verb grammar — mixing clauses incorrectly (SET, REMOVE, ADD, DELETE each have their own syntax), or a stray =.
  • Attribute name with special characters (dots, dashes) used without a placeholder.

How to fix it

  1. Alias every attribute name through ExpressionAttributeNames (#status) — it sidesteps the reserved-word list entirely, so aliasing everything is a safe habit.
  2. Define every :value you reference in ExpressionAttributeValues.
  3. Use the right clause. SET to write/overwrite, REMOVE to delete an attribute, ADD for atomic number/set increments, DELETE to remove from a set.

Example

import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
import {DynamoDBDocumentClient, UpdateCommand} from '@aws-sdk/lib-dynamodb';

const doc = DynamoDBDocumentClient.from(new DynamoDBClient({}));

await doc.send(
  new UpdateCommand({
    TableName: 'Orders',
    Key: {pk: 'ORDER#1'},
    // #status aliases the reserved word "status"
    UpdateExpression: 'SET #status = :s, updatedAt = :t',
    ExpressionAttributeNames: {'#status': 'status'},
    ExpressionAttributeValues: {':s': 'SHIPPED', ':t': Date.now()}
  })
);

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.