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 — la ConditionExpression de 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

  1. Lis CancellationReasons sur l'erreur, pas seulement le message. Mappe chaque entrée sur ton élément d'entrée par son index.
  2. Branche selon le code : ConditionalCheckFailed → logique métier ; TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded → réessaie avec un backoff exponentiel ; ValidationError → corrige la requête.
  3. É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

Références

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.

Travaille avec DynamoDB sans la Console

Un client de bureau rapide pour DynamoDB qui exécute le vrai SQL que DynamoDB ne peut pas — JOINs, GROUP BY, agrégations — avec édition visuelle et un agent IA sur tes propres clés Bedrock.

Essai gratuit de 30 jours, sans carte bancaire — ensuite la formule Gratuit, sans limite de durée.