DynamoDB TransactionCanceledException
In breve — Uno (o più) Item nel tuo TransactWriteItems / TransactGetItems è fallito, quindi DynamoDB ha fatto il rollback dell'intera transazione. La vera causa è nell'array CancellationReasons — leggilo; il Code della ragione per Item ti dice esattamente quale Item e perché.
Cosa significa
Le transazioni DynamoDB sono tutto-o-niente. Se la condizione di un Item fallisce, la capacità viene superata, o due transazioni collidono, l'intera cosa viene annullata e nulla viene scritto. Il messaggio di livello superiore è generico:
TransactionCanceledException: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None, TransactionConflict]L'elenco tra parentesi è posizionale — una voce per Item nella tua transazione, in ordine. DynamoDB restituisce questa eccezione con stato HTTP 400, e gli AWS SDK non la riprovano automaticamente — il tuo codice decide, per ogni codice di ragione, se un retry ha senso.
Perché accade (i codici di ragione)
ConditionalCheckFailed— ilConditionExpressiondi quell'Item è risultato falso (vedi ConditionalCheckFailedException).TransactionConflict— un'altra transazione concorrente (o scrittura) sta operando sullo stesso Item; riprova con backoff.ProvisionedThroughputExceeded— la tabella/indice dell'Item ha esaurito la capacità.ThrottlingError— la tabella o l'indice (tipicamente on-demand, mentre DynamoDB la sta ancora scalando) ha fatto throttling sulla scrittura; riprova con backoff.ValidationError— quell'Item era malformato (valori di parametro non validi, document path, tipo di operando, overflow di dimensione, …).ItemCollectionSizeLimitExceeded— una item collection LSI ha raggiunto i 10 GB.None— quell'Item era a posto; il fallimento era altrove nell'elenco.
Questo è l'insieme completo di codici documentato. Nota che una chiave di Item duplicata (lo stesso Item puntato da due azioni) non è un codice di annullamento — DynamoDB rifiuta quella richiesta subito come ValidationException.
Come risolverlo
- Leggi
CancellationReasonsdall'errore, non solo il messaggio. Mappa ogni voce al tuo Item di input tramite l'indice. - Ramifica per codice:
ConditionalCheckFailed→ logica di business;TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded→ riprova con backoff esponenziale;ValidationError→ correggi la richiesta. - Evita chiavi duplicate — una singola transazione non può toccare lo stesso Item due volte.
Modifichi gli item a mano? L'area di staging di DynoTable raggruppa le tue modifiche in un'unica scrittura transazionale e ti lascia rivedere ogni Item prima del commit — la stessa semantica tutto-o-niente senza costruire la richiesta a mano.
Esempio
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
Perché la mia transazione DynamoDB è stata annullata? Un Item nel TransactWriteItems/TransactGetItems è fallito — un controllo di condizione, un limite di throughput/throttling, o un conflitto con un'altra transazione concorrente — quindi DynamoDB ha fatto il rollback dell'intera transazione e non ha scritto nulla. La ragione per-Item è nell'array CancellationReasons.
Come trovo quale Item della transazione è fallito? Leggi l'array CancellationReasons sulla TransactionCanceledException. Ha una voce per Item di input, nello stesso ordine; la voce il cui Code non è "None" è l'Item che ha causato l'annullamento.
Riproducilo
Due scritture in un'unica transazione, la seconda protetta da una condizione che non può essere soddisfatta. L'intera transazione va in rollback, e i verdetti per azione arrivano in CancellationReasons — allineati posizionalmente con 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
}
}
]
})
);Output reale:
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"
}
]La prima azione riporta None — non è fallita, ha subito il rollback perché è fallita quella accanto. Solo la voce il cui Code non è None identifica il vero colpevole, e il suo indice è l'indice dell'azione problematica nel tuo array TransactItems.
Errori correlati
- ConditionalCheckFailedException
- ProvisionedThroughputExceededException
- Esempio di codice: TransactWriteItems in Node.js · in Python (boto3) — una transazione eseguibile da confrontare.
- Impara: DynamoDB transactions
Riferimenti
- 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
Ultima verifica 2026-07-13 rispetto alla documentazione ufficiale AWS collegata sopra.
Riprodotto il 2026-07-26 su DynamoDB Local 2.x con AWS SDK for JavaScript v3.1095.0 — l'output qui sopra è riportato alla lettera.