ValidationException: ExpressionAttributeValues contains invalid value
TL;DR — A value in ExpressionAttributeValues is empty, has an unsupported type, or a :placeholder used in your expression was never defined. Check every :value is present and non-empty.
What it means
Common messages:
ValidationException: ExpressionAttributeValues contains invalid value: One or more parameter values were invalid: An AttributeValue may not contain an empty string for key :s
ValidationException: Value provided in ExpressionAttributeValues unused in expressions: keys: {:x}
ValidationException: An expression attribute value used in expression is not defined; attribute value: :vWhy it happens
- Empty string / empty binary — historically DynamoDB rejected
"". Empty strings are now allowed for non-key attributes (and empty Lists/Maps are fine), but empty values in key attributes and empty Sets are still invalid. - Undefined placeholder — your expression references
:vbutExpressionAttributeValueshas no:v. - Unused placeholder — you defined
:xbut no expression uses it (DynamoDB rejects the whole request). - Wrong type — passing a raw JS object/
undefined/NaN, or (with the low-level client) the wrong{S}/{N}wrapper. - An empty set passed to an
ADD/DELETEoperation — those clauses take set (or, forADD, number) operands, and a set can never be empty.
How to fix it
- Every
:valuein the expression must be defined inExpressionAttributeValues, and every defined value must be used — keep the two in exact sync. - Guard against empty/
undefined. Don't pass:vwhen the source isundefined; drop the clause instead. For sets, ensure at least one member. - Use the Document Client (
@aws-sdk/lib-dynamodb) so native JS values are marshalled for you — it removes most type-wrapper mistakes. - Audit the map against the expression string. Print both side by side before the call — every
:tokenin the expression must appear as a key inExpressionAttributeValues, and every key in the map must appear in the expression. - For low-level clients, validate wire types. An empty set
{SS: []}or a missing type wrapper on a key attribute still fails even when the placeholder is defined.
Example
import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
import {DynamoDBDocumentClient, UpdateCommand} from '@aws-sdk/lib-dynamodb';
const doc = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const email = getEmail(); // could be undefined
const names = {'#e': 'email'};
const values = {':e': email};
if (email == null) throw new Error('email required'); // don't send :e = undefined
await doc.send(
new UpdateCommand({
TableName: 'Users',
Key: {pk: 'USER#1'},
UpdateExpression: 'SET #e = :e',
ExpressionAttributeNames: names,
ExpressionAttributeValues: values
})
);Path in DynoTable
DynoTable's update editor binds values as you type and rejects empty placeholders before the request leaves your machine. Open the item with ⌘K, edit a field, and inspect the generated ExpressionAttributeValues map in the request preview — mismatches show up immediately instead of as a 400 in CloudWatch.
For SDK code you cannot run inline, paste the expression into the Expression Builder and diff its :value map against yours. Switch profiles with ⌘P to test against the same table that threw the error; Test Connection on Settings → Profiles confirms credentials and region. Setup: Connect to AWS, Install. Empty sets and undefined JS values are the most common causes — guard both before the call leaves your process.
Sources
- PutItem — Amazon DynamoDB API Reference (verified 2026-07-13)
- Constraints in Amazon DynamoDB (verified 2026-07-13)
Related errors
References
- PutItem — Amazon DynamoDB API Reference
- Constraints in Amazon DynamoDB — Amazon DynamoDB Developer Guide
- Using update expressions in DynamoDB — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.