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: key :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, 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. - Empty list/map where a non-empty value is required by your
ADD/DELETEset operation.
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.
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
})
);