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— oConditionExpressiondaquele 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
- Leia
CancellationReasonsdo erro, não apenas a mensagem. Mapeie cada entrada de volta ao seu item de entrada por índice. - Ramifique por código:
ConditionalCheckFailed→ lógica de negócio;TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded→ tente novamente com backoff exponencial;ValidationError→ corrija a requisição. - 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
- ConditionalCheckFailedException
- ProvisionedThroughputExceededException
- Exemplo de código: TransactWriteItems in Node.js · in Python (boto3) — uma transação executável para comparar.
- Aprenda: DynamoDB transactions
Referências
- TransactWriteItems — Amazon DynamoDB API Reference
- TransactGetItems — Amazon DynamoDB API Reference
- Amazon DynamoDB Transactions: How it works — Amazon DynamoDB Developer Guide
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
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.