An operand in the update expression has an incorrect data type
TL;DR — The update's action is type-checked against what's actually stored (and against the value you sent), and one of them doesn't fit: ADD against an attribute that isn't a number or set, list_append against something that isn't a list, or a set operand whose element type doesn't match the stored set. Match the operand to the stored type — or fix the item whose type drifted.
What it means
ValidationException: An operand in the update expression has an incorrect data typeUpdate actions have strict type rules: ADD works only on numbers and sets (SS/NS/BS), DELETE only on sets, and list_append takes two lists. DynamoDB evaluates the expression against the item's current attribute types at write time — so the same request can succeed on one item and fail on another whose attribute holds a different type. A close cousin is rejected earlier, at expression parse time, when the sent value's type can never fit the operator:
ValidationException: Invalid UpdateExpression: Incorrect operand type for
operator or function; operator: ADD, operand type: LISTWhy it happens
ADD counter :onebutcounteris stored as a string — e.g. the item was imported with"5"(typeS) instead of5(typeN).ADD tags :twith a list (L) operand —ADDcollects into sets, not lists. Lists are appended withSET+list_append.list_append(mylist, :v)wheremylistis a map, set, or scalar — both arguments must be lists (wrap a single element as a one-item list).- Set element type mismatch —
ADD/DELETEwith a string set (SS) operand against a stored number set (NS), or vice versa. - Type drift across items — mixed writers (an old import, another service) left the same attribute as
Non some items andSon others, so the update fails only sometimes.
How to fix it
Counters: store the value as a number and send a number operand:
UpdateExpression: 'ADD #c :one', ExpressionAttributeValues: {':one': 1} // {N: "1"} — not a stringLists: use
SETwithlist_append, and wrap the new element in a list:UpdateExpression: 'SET #l = list_append(if_not_exists(#l, :empty), :new)', ExpressionAttributeValues: {':new': ['item'], ':empty': []}Sets: keep
ADD/DELETEoperands the same set type as the stored attribute (SSwithSS,NSwithNS).Fix drifted items — find the items whose attribute carries the wrong type and rewrite them once; the "same update fails on some items" symptom is always data, not code.
Type drift is invisible in most consoles — the DynoTable desktop app displays each attribute's actual stored type next to its value, so a "5"-as-string counter stands out immediately.
Related errors
- Float types are not supported — number-type friction from the SDK side.
- Number overflow
- Type mismatch: key element does not match schema
- Learn: Update expressions · Atomic counters · Data types
References
- Using update expressions in DynamoDB — Amazon DynamoDB Developer Guide
- TransactWriteItems — Amazon DynamoDB API Reference
- Supported data types and naming rules in Amazon DynamoDB — Amazon DynamoDB Developer Guide
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.