DynamoDB IdempotentParameterMismatchException

TL;DR — 直近10分間ですでに使われた ClientRequestTokenTransactWriteItems を呼び出しましたが、リクエストの残りが変わっていました。トークンは「これは 同じ トランザクションのリトライだ」と約束するため、DynamoDB はペイロードが異なるトークンの再利用を拒否します。バイト単位で同一のリトライにのみトークンを再利用し、すべての新しい論理トランザクションには新鮮なトークン(UUID)を発行してください。

意味

IdempotentParameterMismatchException: DynamoDB rejected the request because
you retried a request with a different payload but with an idempotent token
that was already used.

ClientRequestTokenTransactWriteItems を冪等にします。同じトークンでの複数の同一呼び出しは1回の呼び出しの効果を持ち、タイムアウトが最初の試行が到達したかどうかを隠すときにトランザクションの二重適用から守ります。トークンは、それを使った最初のリクエストが完了してから 10分間 有効なままです。そのウィンドウ内に同じトークンで 異なるパラメータ のリクエストが到達すると、DynamoDB はそれをリトライとして扱えず、新しいトランザクションとしても扱うことを拒否します。HTTP 400、そのままではリトライ不可です。

発生する理由

  • 静的またはハードコードされたトークン — すべてのトランザクションに同じトークン文字列が送られるため、2つ目の(異なる)トランザクションが最初のものと衝突する。
  • 粗すぎるものから導出されたトークン — 例: ユーザー ID やテーブル名。そのため同じユーザーの2つの異なるトランザクションがトークンを共有する。
  • リトライがリクエストを別様に再構築した — タイムスタンプ、TTL 値、またはアイテム内の生成された ID が、試行1とリトライの間で変わったため、「同じ」トランザクションがもはやバイト単位で一致しない。
  • 2つのコードパスがトークンソースを共有 — 同じ値でシードされた並列ワーカー。

修正方法

  1. 論理トランザクションごとに一意のトークンを生成します — トランザクションが組み立てられる時点で UUID を:

    import {randomUUID} from 'node:crypto';
    
    await client.send(new TransactWriteItemsCommand({
      ClientRequestToken: token, // created ONCE per logical transaction
      TransactItems: [...]
    }));
  2. リトライ時はトークンをリクエスト とともに 保持します — 再構築したものではなく、すでに組み立てたリクエストオブジェクトを再試行し、ペイロード内の何もドリフトできないようにします。(AWS SDK は自動リトライでこれを正しく行います。バグはほぼ必ず、リクエストを再構成するアプリケーションレベルのリトライです。)

  3. 揮発性の値を組み立て前に固定します — タイムスタンプと生成された ID は一度計算して再利用し、リトライ時に再評価しないようにします。

  4. 10分後にトークンを再利用して冪等性を期待しないでください — ウィンドウを過ぎると、リクエストは新規として扱われ、再び適用されます。

DynoTable デスクトップアプリ は、トランザクションが触れた正確なアイテムを検査できるため、「最初の試行は実際に到達したか?」が推測ではなくルックアップになります。

関連するエラー

References

最終検証日 2026-07-13、上記にリンクした公式 AWS ドキュメントに照らして確認しました。

Console なしで DynamoDB を扱う

DynoTable は DynamoDB 向けの高速なデスクトップクライアントです — テーブルを閲覧し、SQL スタイルのクエリを実行し、アイテムをローカルで編集できます。