DynamoDB TransactionCanceledException — ConditionalCheckFailed

TL;DR — Seu TransactWriteItems foi cancelado e o array CancellationReasons contém uma entrada ConditionalCheckFailed. Uma das condition expressions da transação não se sustentou, então o DynamoDB reverteu cada ação atomicamente. Leia o array de reasons — suas entradas são posicionais, uma por item solicitado — para descobrir qual condição de item falhou, depois corrija a pré-condição desse item ou os dados.

O que significa

TransactionCanceledException: Transaction cancelled, please refer cancellation
reasons for specific reasons [ConditionalCheckFailed, None, None]
# CancellationReasons[0] = { Code: "ConditionalCheckFailed",
#                            Message: "The conditional request failed" }

TransactWriteItems é tudo-ou-nada. Se qualquer ConditionExpression de uma única ação avaliar como falso, o DynamoDB cancela a requisição inteira e reporta uma lista de reasons por item. ConditionalCheckFailed na posição i significa que a condição do i-ésimo item não foi satisfeita — a transação nunca foi aplicada parcialmente.

Por que acontece

  • Falha de optimistic-lock — um guard version = :v / attribute_not_exists(pk) falhou porque outro processo de escrita já alterou ou criou o item.
  • Guard de unicidade disparado — uma inserção attribute_not_exists(pk) perdeu uma corrida, então o item já existe.
  • Leitura desatualizada — a condição foi construída a partir de um valor que mudou desde então.
  • Leitura errada da lista de reasons — o array é posicional, ordenado como seus TransactItems; um None em uma posição significa que aquele item estava OK, ConditionalCheckFailed marca o que falhou. (Outros códigos no array — TransactionConflict, ItemCollectionSizeLimitExceeded, ProvisionedThroughputExceeded, ThrottlingError, ValidationError — significam algo diferente.)

Como corrigir

  1. Inspecione CancellationReasons na exceção e encontre o índice com ConditionalCheckFailed — essa é a ação que falhou.
  2. Releia o item e decida: tentar novamente com uma pré-condição fresca (loop de retry de optimistic-lock) ou apresentar um conflito ao chamador.
  3. Corrija a condição se ela estiver errada — por exemplo, attribute_not_exists(pk) em um item que legitimamente já existe.
  4. Adicione ReturnValuesOnConditionCheckFailure: ALL_OLD à ação que falha para que o DynamoDB retorne o item que quebrou a condição (ótimo para depuração).
  5. Limite suas tentativas — uma condição que falha persistentemente é um conflito de negócio real, não um erro transitório; não tente novamente para sempre.

Depurando uma transação que falhou na mão? Inspecione o estado atual do item no app desktop DynoTable para ver exatamente por que a pré-condição não se sustentou antes de tentar novamente.

FAQ

Como sei qual item na minha transação falhou? Leia o array CancellationReasons no TransactionCanceledException. Ele é posicional — uma entrada por item solicitado, em ordem. A entrada com código ConditionalCheckFailed identifica a ação cuja condition expression avaliou como falso; entradas com código None foram bem-sucedidas.

Um ConditionalCheckFailed dentro de uma transação é retentável? Não automaticamente. É um conflito de pré-condição real, não um erro transitório. Releia o item, decida se a escrita ainda se aplica e tente novamente com uma condição fresca — ou apresente o conflito ao usuário.

Erros relacionados

Referências

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

Trabalhe com o DynamoDB sem o Console

O DynoTable é um cliente desktop rápido para o DynamoDB — navegue pelas tabelas, execute consultas no estilo SQL e edite itens localmente.