DynamoDB TransactionCanceledException
TL;DR — Un (ou plusieurs) élément(s) de ton TransactWriteItems / TransactGetItems a échoué, donc DynamoDB a annulé la transaction entière. La vraie cause est dans le tableau CancellationReasons — lis-le ; le Code de motif par élément t'indique exactement quel élément et pourquoi.
Ce que ça signifie
Les transactions DynamoDB sont du tout-ou-rien. Si la condition d'un élément échoue, si la capacité est dépassée, ou si deux transactions entrent en collision, l'ensemble est annulé et rien n'est écrit. Le message de premier niveau est générique :
TransactionCanceledException: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None, TransactionConflict]La liste entre crochets est positionnelle — une entrée par élément de ta transaction, dans l'ordre. DynamoDB renvoie cette exception avec le statut HTTP 400, et les SDK AWS ne la réessaient pas automatiquement — c'est ton code qui décide, motif par motif, si un retry a du sens.
Pourquoi ça arrive (les codes de motif)
ConditionalCheckFailed— laConditionExpressionde cet élément a été évaluée à faux (voir ConditionalCheckFailedException).TransactionConflict— une autre transaction concurrente (ou écriture) opère sur le même élément ; réessaie avec backoff.ProvisionedThroughputExceeded— la table/l'index de l'élément a épuisé sa capacité.ThrottlingError— la table ou l'index (typiquement à la demande, pendant que DynamoDB est encore en train de faire la montée en charge) a throttlé l'écriture ; réessaie avec backoff.ValidationError— cet élément était mal formé (valeurs de paramètre invalides, chemin de document, type d'opérande, dépassement de taille, …).ItemCollectionSizeLimitExceeded— une item collection de LSI a atteint 10 Go.None— cet élément était correct ; l'échec était ailleurs dans la liste.
C'est l'ensemble complet des codes documentés. Note qu'une clé d'élément en double (le même élément ciblé par deux actions) n'est pas un code d'annulation — DynamoDB rejette cette requête d'emblée sous forme de ValidationException.
Comment le corriger
- Lis
CancellationReasonssur l'erreur, pas seulement le message. Mappe chaque entrée sur ton élément d'entrée par son index. - Branche selon le code :
ConditionalCheckFailed→ logique métier ;TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded→ réessaie avec un backoff exponentiel ;ValidationError→ corrige la requête. - Évite les clés en double — une seule transaction ne peut pas toucher deux fois le même élément.
Tu modifies des éléments à la main ? La zone de staging de DynoTable regroupe tes modifications en une seule écriture transactionnelle et te laisse relire chaque élément avant de committer — la même sémantique tout-ou-rien sans construire la requête à la main.
Exemple
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
Pourquoi ma transaction DynamoDB a-t-elle été annulée ? Un élément du TransactWriteItems/TransactGetItems a échoué — une vérification de condition, une limite de débit/throttling, ou un conflit avec une autre transaction concurrente — donc DynamoDB a annulé toute la transaction et n'a rien écrit. Le motif par élément est dans le tableau CancellationReasons.
Comment trouver quel élément de la transaction a échoué ? Lis le tableau CancellationReasons sur la TransactionCanceledException. Il a une entrée par élément d'entrée, dans le même ordre ; l'entrée dont le Code n'est pas « None » est l'élément qui a causé l'annulation.
Reproduire l'erreur
Deux écritures dans une même transaction, la seconde gardée par une condition qui ne peut pas tenir. La transaction entière est annulée, et les verdicts par action arrivent dans CancellationReasons — alignés positionnellement sur 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
}
}
]
})
);Sortie réelle :
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 première action rapporte None — elle n'a pas échoué, elle a été annulée parce que sa voisine, elle, a échoué. Seule l'entrée dont le Code n'est pas None identifie le vrai coupable, et son index est celui de l'action fautive dans ton propre tableau TransactItems.
Erreurs liées
- ConditionalCheckFailedException
- ProvisionedThroughputExceededException
- Exemple de code : TransactWriteItems en Node.js · en Python (boto3) — une transaction exécutable à comparer.
- En savoir plus : Transactions DynamoDB
Références
- 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
Dernière vérification le 2026-07-13 par rapport à la documentation officielle AWS liée ci-dessus.
Reproduit le 2026-07-26 sur DynamoDB Local 2.x avec l'AWS SDK for JavaScript v3.1095.0 — la sortie ci-dessus est reproduite telle quelle.