DynamoDB TransactionCanceledException

TL;DR — One (or more) items in your TransactWriteItems / TransactGetItems failed, so DynamoDB rolled back the entire transaction. The real cause is in the CancellationReasons array — read it; the reason Code per item tells you exactly which item and why.

What it means

DynamoDB transactions are all-or-nothing. If any item's condition fails, capacity is exceeded, or two transactions collide, the whole thing is cancelled and nothing is written. The top-level message is generic:

TransactionCanceledException: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None, TransactionConflict]

The bracketed list is positional — one entry per item in your transaction, in order.

Why it happens (the reason codes)

  • ConditionalCheckFailed — that item's ConditionExpression evaluated to false (see ConditionalCheckFailedException).
  • TransactionConflict — another concurrent transaction (or write) is operating on the same item; retry with backoff.
  • ProvisionedThroughputExceeded — the item's table/index ran out of capacity.
  • ThrottlingError — request-rate throttle; retry with backoff.
  • ValidationError — that item was malformed.
  • ItemCollectionSizeLimitExceeded — an LSI item collection hit 10 GB.
  • None — that item was fine; the failure was elsewhere in the list.
  • DuplicateItem — the same item key appears twice in one transaction (not allowed).

How to fix it

  1. Read CancellationReasons off the error, not just the message. Map each entry back to your input item by index.
  2. Branch by code: ConditionalCheckFailed → business logic; TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded → retry with exponential backoff; ValidationError → fix the request.
  3. Avoid duplicate keys — a single transaction can't touch the same item twice.

Example

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

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

try {
  await doc.send(new TransactWriteCommand({TransactItems: [/* ... */]}));
} catch (err) {
  if (err instanceof TransactionCanceledException) {
    for (const [i, reason] of (err.CancellationReasons ?? []).entries()) {
      if (reason.Code && reason.Code !== 'None') {
        console.error(`item ${i} cancelled: ${reason.Code}${reason.Message}`);
      }
    }
  }
  throw err;
}

FAQ

Why did my DynamoDB transaction get cancelled? One item in the TransactWriteItems/TransactGetItems failed — a condition check, a throughput/throttling limit, or a conflict with another concurrent transaction — so DynamoDB rolled the whole transaction back and wrote nothing. The per-item reason is in the CancellationReasons array.

How do I find which item in the transaction failed? Read the CancellationReasons array on the TransactionCanceledException. It has one entry per input item, in the same order; the entry whose Code is not "None" is the item that caused the cancellation.

不必透過主控台就能操作 DynamoDB

DynoTable 是一款快速的 DynamoDB 桌面用戶端 — 瀏覽表格、執行 SQL 風格的查詢,並在本機編輯項目。