DuplicateItemException: duplicate primary key

TL;DR — PartiQL INSERT は厳密な作成です。同じプライマリキーを持つアイテムがすでに存在すると、DynamoDB はそれを上書きするのではなく DuplicateItemException をスローします。既存のアイテムを変更するには PartiQL UPDATE を使い、PutItem の「存在すれば置換」のセマンティクスを得るには PutItem 自体を使ってください。PartiQL INSERT は意図的に決して置換しません。

意味

DuplicateItemException: There was an attempt to insert an item with the
same primary key as an item that already exists in the DynamoDB table.

PartiQL データプレーン(ExecuteStatement / ExecuteTransaction / BatchExecuteStatement)は INSERT を条件付き作成にマッピングします。そのプライマリキーを持つアイテムが存在しない場合にのみ成功します。これはネイティブの PutItem とは逆のデフォルトで、PutItem は既存のアイテムを黙って置換します。INSERT が重複キーで失敗することを期待して SQL から来たなら、これはまさにその挙動です。upsert のセマンティクスを期待していたなら、このエラーは意外でしょう。

発生する理由

  • アイテムが本当にすでに存在する — リトライ、リプレイ、あるいは同じキーで競合する2つのライターが両方とも INSERT を発行している。
  • 作成ではなく更新をしたかったPutItem スタイルのコードを PartiQL に移植し、INSERT が置換すると仮定した。
  • 冪等でないリトライループ — 最初の試行は成功したがレスポンスが失われ(タイムアウト)、リトライが同じキーを再挿入する。
  • 一意でない合成キー — 組み立てたパーティション/ソートキーが思ったより頻繁に衝突する(例: 秒精度のタイムスタンプ)。

修正方法

  1. 既存のアイテムを更新しますか?UPDATE を使います:

    UPDATE "orders" SET status = 'shipped' WHERE pk = 'ORDER#123' AND sk = 'META'
  2. 存在すれば置換(PutItem のセマンティクス)が欲しいですか?PutItem を呼び出します — PartiQL に upsert 文はなく、ネイティブ API のデフォルトはまさにあなたの求める上書きです:

    await client.send(new PutItemCommand({TableName: 'orders', Item: item}));
  3. 作成が冪等な場合は成功として扱います — リトライが、最初の試行がすでに書き込んだアイテムに対して DuplicateItemException に遭遇した場合、それをキャッチして無視するのが正しい処理であることが多いです。

  4. 一意性に依存する場合は INSERT を維持します — この例外はあなたの作成専用ガードであり、PutItem 条件での attribute_not_exists() の PartiQL 版です。

実データに対して文を試すのが、INSERT/UPDATE の違いを体得する最速の方法です。DynoTable デスクトップアプリ はライブテーブルに対して SQL ワークベンチで PartiQL を実行し、DynamoDB Expression Builder は代わりに PutItem のセマンティクスが必要なとき、それに相当するネイティブ API リクエストを出力します。

関連するエラー

References

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

Console なしで DynamoDB を扱う

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