DynamoDB TransactionCanceledException

TL;DR — Um (ou mais) itens no seu TransactWriteItems / TransactGetItems falhou, então o DynamoDB reverteu a transação inteira. A causa real está no array CancellationReasons — leia-o; o Code do reason por item te diz exatamente qual item e por quê.

O que significa

Transações do DynamoDB são tudo-ou-nada. Se a condição de qualquer item falha, a capacidade é excedida, ou duas transações colidem, tudo é cancelado e nada é escrito. A mensagem de nível superior é genérica:

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

A lista entre colchetes é posicional — uma entrada por item na sua transação, em ordem. O DynamoDB retorna esta exceção com status HTTP 400, e os AWS SDKs não a tentam novamente automaticamente — seu código decide, por código de reason, se um retry faz sentido.

Por que acontece (os códigos de reason)

  • ConditionalCheckFailed — o ConditionExpression daquele item avaliou como falso (veja ConditionalCheckFailedException).
  • TransactionConflict — outra transação concorrente (ou escrita) está operando no mesmo item; tente novamente com backoff.
  • ProvisionedThroughputExceeded — a tabela/índice do item ficou sem capacidade.
  • ThrottlingError — a tabela ou índice (tipicamente on-demand, enquanto o DynamoDB ainda está escalando-a) fez throttle na escrita; tente novamente com backoff.
  • ValidationError — aquele item estava malformado (valores de parâmetro inválidos, document path, tipo de operando, overflow de tamanho, …).
  • ItemCollectionSizeLimitExceeded — uma item collection de LSI atingiu 10 GB.
  • None — aquele item estava OK; a falha estava em outro lugar na lista.

Esse é o conjunto de códigos documentado completo. Note que uma chave de item duplicada (o mesmo item mirado por duas ações) não é um código de cancelamento — o DynamoDB rejeita essa requisição de imediato como um ValidationException em vez disso.

Como corrigir

  1. Leia CancellationReasons do erro, não apenas a mensagem. Mapeie cada entrada de volta ao seu item de entrada por índice.
  2. Ramifique por código: ConditionalCheckFailed → lógica de negócio; TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded → tente novamente com backoff exponencial; ValidationError → corrija a requisição.
  3. Evite chaves duplicadas — uma única transação não pode tocar o mesmo item duas vezes.

Editando itens à mão? A área de preparação do DynoTable agrupa suas edições em uma única escrita transacional e deixa você revisar cada item antes de fazer commit — a mesma semântica tudo-ou-nada sem montar a requisição à mão.

Exemplo

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

Por que minha transação do DynamoDB foi cancelada? Um item no TransactWriteItems/TransactGetItems falhou — uma verificação de condição, um limite de throughput/throttling, ou um conflito com outra transação concorrente — então o DynamoDB reverteu a transação inteira e não escreveu nada. O reason por item está no array CancellationReasons.

Como encontro qual item na transação falhou? Leia o array CancellationReasons no TransactionCanceledException. Ele tem uma entrada por item de entrada, na mesma ordem; a entrada cujo Code não é "None" é o item que causou o cancelamento.

Reproduza

Duas escritas em uma transação, a segunda protegida por uma condição que não pode se sustentar. A transação inteira é revertida, e os veredictos por ação chegam em CancellationReasons — alinhados posicionalmente com TransactItems:

await client.send(
  new TransactWriteItemsCommand({
    TransactItems: [
      {Put: {TableName: 'orders', Item: {pk: {S: 'OK'}, sk: {S: 'META'}}}},
      {
        Put: {
          TableName: 'orders',
          Item: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}},
          ConditionExpression: 'attribute_not_exists(pk)' // ORDER#1 already exists
        }
      }
    ]
  })
);

Saída real:

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

error.CancellationReasons:
[
  {
    "Code": "None"
  },
  {
    "Code": "ConditionalCheckFailed",
    "Message": "The conditional request failed"
  }
]

A primeira ação reporta None — ela não falhou, foi revertida porque a vizinha falhou. Só a entrada cujo Code não é None identifica o culpado de verdade, e o índice dela é o índice da ação problemática no seu próprio array TransactItems.

Erros relacionados

Referências

Verificado pela última vez em 2026-07-13 contra a documentação oficial da AWS vinculada acima.

Reproduzido em 2026-07-26 no DynamoDB Local 2.x com o AWS SDK for JavaScript v3.1095.0 — a saída acima é literal.

Trabalhe com o DynamoDB sem o Console

Um cliente desktop rápido para DynamoDB que roda o SQL de verdade que o DynamoDB não consegue — JOINs, GROUP BY, agregações — com edição visual e um agente de IA com suas próprias chaves do Bedrock.

Teste grátis de 30 dias, sem cartão de crédito — depois o plano Grátis sem limite de tempo.