DynamoDB TransactionCanceledException
TL;DR — TransactWriteItems / TransactGetItems の中の1つ(または複数)のアイテムが失敗したため、DynamoDB は トランザクション全体 をロールバックしました。本当の原因は CancellationReasons 配列にあります — それを読んでください。アイテムごとの理由 Code が、どのアイテムがなぜ失敗したかを正確に教えてくれます。
意味
DynamoDB のトランザクションはオール・オア・ナッシングです。いずれかのアイテムの条件が失敗するか、キャパシティを超過するか、2つのトランザクションが衝突すると、全体がキャンセルされ、何も書き込まれません。トップレベルのメッセージは一般的なものです。
TransactionCanceledException: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None, TransactionConflict]角括弧のリストは 位置対応 です — トランザクション内のアイテムごとに1エントリ、順番どおりに並びます。DynamoDB はこの例外を HTTP ステータス 400 で返し、AWS SDK は自動では リトライしません — 理由コードごとに、リトライが妥当かどうかはあなたのコードが決めます。
発生する理由(理由コード)
ConditionalCheckFailed— そのアイテムのConditionExpressionが false と評価された(ConditionalCheckFailedException を参照)。TransactionConflict— 別の並行トランザクション(または書き込み)が同じアイテムを操作している。バックオフしてリトライしましょう。ProvisionedThroughputExceeded— そのアイテムのテーブル/インデックスがキャパシティを使い切った。ThrottlingError— テーブルまたはインデックス(典型的にはオンデマンドで、DynamoDB がまだスケール中)が書き込みをスロットリングした。バックオフしてリトライしましょう。ValidationError— そのアイテムが不正な形式だった(無効なパラメータ値、ドキュメントパス、オペランド型、サイズ超過など)。ItemCollectionSizeLimitExceeded— LSI のアイテムコレクションが 10 GB に達した。None— そのアイテムには問題がなかった。失敗はリストの別の場所にあります。
これがドキュメント化されたコードの全集合です。重複したアイテムキー(2つのアクションが同じアイテムを対象にする)はキャンセルコードではないことに注意してください — DynamoDB はそのリクエストを事前に ValidationException として拒否します。
修正方法
- メッセージだけでなく、エラーから
CancellationReasonsを読みます。 各エントリをインデックスで入力アイテムに対応づけましょう。 - コードで分岐します:
ConditionalCheckFailed→ ビジネスロジック、TransactionConflict/ThrottlingError/ProvisionedThroughputExceeded→ 指数バックオフでリトライ、ValidationError→ リクエストを修正。 - 重複キーを避けます — 1つのトランザクションが同じアイテムに2回触れることはできません。
アイテムを手作業で編集していますか? DynoTable のステージングエリアは編集を1つのトランザクション書き込みにまとめ、コミット前にすべてのアイテムを確認させてくれます — リクエストを手で組み立てずに、同じオール・オア・ナッシングのセマンティクスが得られます。
例
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;
}よくある質問
DynamoDB のトランザクションはなぜキャンセルされたのですか? TransactWriteItems/TransactGetItems の中の1つのアイテムが失敗しました — 条件チェック、スループット/スロットリングの上限、あるいは別の並行トランザクションとの競合です。そのため DynamoDB はトランザクション全体をロールバックし、何も書き込みませんでした。アイテムごとの理由は CancellationReasons 配列にあります。
トランザクション内のどのアイテムが失敗したかを見つけるには? TransactionCanceledException の CancellationReasons 配列を読みます。入力アイテムごとに1エントリが同じ順序で並んでおり、Code が「None」でないエントリが、キャンセルの原因となったアイテムです。
再現方法
1つのトランザクション内の2つの書き込みで、2つ目は成立しえない条件でガードします。トランザクション全体がロールバックされ、アクションごとの判定が CancellationReasons に — 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
}
}
]
})
);実際の出力:
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"
}
]最初のアクションは None を報告します — それ自体は失敗しておらず、隣のアクションが失敗したためにロールバックされたのです。実際の犯人を特定できるのは Code が None でないエントリだけで、そのインデックスは自分の TransactItems 配列における問題のアクションのインデックスです。
関連するエラー
- ConditionalCheckFailedException
- ProvisionedThroughputExceededException
- Code example: TransactWriteItems in Node.js · in Python (boto3) — 比較できる実行可能なトランザクション。
- 学習: DynamoDB のトランザクション
参考資料
- 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
最終検証日 2026-07-13、上記にリンクした公式 AWS ドキュメントに照らして確認しました。
2026-07-26 に DynamoDB Local 2.x と AWS SDK for JavaScript v3.1095.0 で再現しました — 上記の出力はそのままの逐語です。