Two document paths overlap with each other

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

意味

ValidationException: 1 validation error detected: 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 = :e は、profile = :p がマップ全体を置き換える前に走るのか後なのか? 推測するのではなく、DynamoDB はその式をきっぱり拒否します。(同じ重複チェックは ProjectionExpression の重複パスにも適用されます。)

発生する理由

  • 1つの式で親とその子を設定しているSET profile = :p, profile.email = :e。2つ目のパスは1つ目の内側にあります。
  • 同じ属性が2回登場するSET updatedAt = :a REMOVE updatedAtSET tags = :t ADD tags :more
  • ODM/ラッパーが、自分でも設定しているパスを黙って追加する — 典型的なケースです。ライブラリがタイムスタンプやオブジェクト全体(SET item = :obj)を自動で書き込む一方で、自分のコードも item.field を設定している(Dynamoose の自動 createdAt/updatedAt で見られます)。
  • リストとその要素の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つのリクエストに分割しますUpdateItem を2回、順番に。

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

再現方法

1つの UpdateExpression で、マップと、その同じマップ内のフィールドの両方を設定します。

await client.send(
  new UpdateItemCommand({
    TableName: 'orders',
    Key: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}},
    UpdateExpression: 'SET #a = :v, #a.#b = :w',
    ExpressionAttributeNames: {'#a': 'addr', '#b': 'city'},
    ExpressionAttributeValues: {':v': {M: {}}, ':w': {S: 'Berlin'}}
  })
);

実際の出力:

ValidationException: 1 validation error detected: Invalid UpdateExpression: Two document paths overlap with each other; must remove or rewrite one of these paths; path one: [addr], path two: [addr, city]
HTTP 400

メッセージは衝突する両方のパスを完全な形で出力するので、どのペアを調整すべきかが正確に分かります。両方が適用された場合の順序は未定義であり、だから DynamoDB はどちらかを選ぶのではなく拒否するのです。

関連するエラー

参考資料

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

2026-07-26 に DynamoDB Local 2.x と AWS SDK for JavaScript v3.1095.0 で再現しました — 上記の出力はそのままの逐語です。

Console なしで DynamoDB を扱う

DynamoDB では実行できない本物の SQL(JOINs、GROUP BY、集計)を実行する高速な DynamoDB デスクトップクライアント。ビジュアル編集と、あなた自身の Bedrock キーで動く AI エージェントを備えています。

30日間無料トライアル、クレジットカード不要 — その後は期限のない Free プラン。