Two document paths overlap with each other

TL;DR — 1つの UpdateExpression は各ドキュメントパスに 1 回だけ触れることができ、どのパスも、同じ式が触れる別のパスの 内部 にあってはなりません。SET profile = :p, profile.email = :e は重複します(profile.emailprofile の内部にあります)。同じ属性を2回指定するのも同様です。子を親の値に折り込むか、2つの更新に分割してください。

意味

ValidationException: Invalid UpdateExpression: Two document paths overlap
with each other; must remove or rewrite one of these paths;
path one: [profile], path two: [profile, email]

DynamoDB は UpdateExpression 内のすべてのアクションを、更新前のアイテムの属性値 に対して評価します。アクションは左から右へ次々と適用されるわけではありません。2つのアクションが重複するパス(同じ属性、または親とその内部にネストされたもの)を対象とすると、結果は曖昧になります: profile.email = :eprofile = :p がマップ全体を置き換える前に実行されるのか後なのか?推測するのではなく、DynamoDB は式をそのまま拒否します。(同じ重複チェックは ProjectionExpression 内の重複パスにも適用されます。)

発生する理由

  • 1つの式で親とその子を設定SET profile = :p, profile.email = :e。2つ目のパスが1つ目の内部にあります。
  • 同じ属性が2回現れるSET updatedAt = :a REMOVE updatedAt、または SET tags = :t ADD tags :more
  • ODM/ラッパーが、あなたも設定するパスを黙って追加 — 典型例: ライブラリがタイムスタンプやオブジェクト全体(SET item = :obj)を自動書き込みする一方、あなたのコードも item.field を設定する(自動 createdAt/updatedAt を持つ Dynamoose で見られる)。
  • リストとその要素の1つを一緒に更新SET mylist = :l, mylist[0] = :v

修正方法

  1. 子を親の値に折り込みます — どのみちマップを置き換えるなら、新しい email をその中に入れ、2つ目のアクションを削除します:

    // instead of SET profile = :p, profile.email = :e
    UpdateExpression: 'SET #p = :p',
    ExpressionAttributeValues: {':p': {name: 'Ada', email: 'ada@example.com'}}
  2. またはリーフのみを更新します — 親をそのままにして、ネストされたフィールドを個別に設定します(SET #p.#n = :n, #p.#e = :e)。同じ親の下の兄弟パスは重複しません。ネストのみが重複します。

  3. 重複排除します — 各属性が SET/REMOVE/ADD/DELETE にまたがって正確に 1 つのアクションに現れることを確認します。

  4. ライブラリの自動フィールドを確認します — 自分の式がすでに書き込む更新から、自動管理される属性(タイムスタンプ、バージョン)を無効化または除外します。

  5. 本当に「親を置き換えてから子を微調整」のセマンティクスが必要なときは、2つのリクエストに分割します — 順序どおりの2つの UpdateItem 呼び出し。

ネストされたマップを手作業で編集するところに重複が忍び込みます。DynoTable デスクトップアプリ はアイテムの属性をインプレースで編集し、変更されたものだけに対してクリーンで重複のない更新を発行します。

関連するエラー

References

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

Console なしで DynamoDB を扱う

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