DynamoDB TransactionCanceledException — ConditionalCheckFailed
TL;DR — Your TransactWriteItems was canceled and the CancellationReasons array holds a ConditionalCheckFailed entry. One of the transaction's condition expressions didn't hold, so DynamoDB rolled back every action atomically. Read the reasons array — its entries are positional, one per requested item — to find which item's condition failed, then fix that item's precondition or the data.
What it means
TransactionCanceledException: Transaction cancelled, please refer cancellation
reasons for specific reasons [ConditionalCheckFailed, None, None]
# CancellationReasons[0] = { Code: "ConditionalCheckFailed",
# Message: "The conditional request failed" }TransactWriteItems is all-or-nothing. If any single action's ConditionExpression evaluates false, DynamoDB cancels the whole request and reports a per-item reason list. ConditionalCheckFailed at position i means the i-th item's condition wasn't met — the transaction never partially applied.
Why it happens
- Optimistic-lock miss — a
version = :v/attribute_not_exists(pk)guard failed because another writer already changed or created the item. - Uniqueness guard tripped — an
attribute_not_exists(pk)insert lost a race, so the item already exists. - Stale read — the condition was built from a value that has since changed.
- Reason list misread — the array is positional, ordered like your
TransactItems; aNoneat a slot means that item was fine,ConditionalCheckFailedmarks the one that failed. (Other codes in the array —TransactionConflict,ItemCollectionSizeLimitExceeded,ProvisionedThroughputExceeded,ThrottlingError,ValidationError— mean something different.)
How to fix it
- Inspect
CancellationReasonsin the exception and find the index withConditionalCheckFailed— that's the failing action. - Re-read the item and decide: retry with a fresh precondition (optimistic-lock retry loop) or surface a conflict to the caller.
- Fix the condition if it's wrong — e.g.
attribute_not_exists(pk)on an item that legitimately already exists. - Add
ReturnValuesOnConditionCheckFailure: ALL_OLDto the failing action so DynamoDB returns the item that broke the condition (great for debugging). - Bound your retries — a persistently failing condition is a real business conflict, not a transient error; don't retry forever.
Debugging a failed transaction by hand? Inspect the current item state in the DynoTable desktop app to see exactly why the precondition didn't hold before you retry.
FAQ
How do I know which item in my transaction failed?
Read the CancellationReasons array on the TransactionCanceledException. It's positional — one entry per requested item, in order. The entry with code ConditionalCheckFailed identifies the action whose condition expression evaluated false; entries with code None succeeded.
Is a ConditionalCheckFailed inside a transaction retryable? Not automatically. It's a real precondition conflict, not a transient error. Re-read the item, decide whether the write still applies, and retry with a fresh condition — or surface the conflict to the user.
Related errors
- ConditionalCheckFailedException — the same failure on a single non-transactional write.
- TransactionCanceledException (overview) — all cancellation reason codes.
- TransactionConflictException — a concurrent transaction on the same item.
- Code example: TransactWriteItems in Node.js · in Python (boto3) — a working conditioned transaction to adapt.
- Learn: DynamoDB transactions · Condition expressions
References
- TransactWriteItems — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
- DynamoDB condition expression examples — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.