Two document paths overlap with each other
TL;DR — 1つの UpdateExpression が各ドキュメントパスに触れられるのは1回だけで、同じ式が触れる別のパスの 内側 にあるパスも触れられません。SET profile = :p, profile.email = :e は重複します(profile.email は profile の内側にあります)。同じ属性を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 updatedAtやSET tags = :t ADD tags :more。 - ODM/ラッパーが、自分でも設定しているパスを黙って追加する — 典型的なケースです。ライブラリがタイムスタンプやオブジェクト全体(
SET item = :obj)を自動で書き込む一方で、自分のコードもitem.fieldを設定している(Dynamoose の自動createdAt/updatedAtで見られます)。 - リストとその要素の1つを一緒に更新している —
SET mylist = :l, mylist[0] = :v。
修正方法
子を親の値に畳み込みます — どのみちマップを置き換えるなら、新しい email をその中に入れて2つ目のアクションを落とします:
// instead of SET profile = :p, profile.email = :e UpdateExpression: 'SET #p = :p', ExpressionAttributeValues: {':p': {name: 'Ada', email: 'ada@example.com'}}または葉だけを更新します — 親には触れず、ネストしたフィールドを個別に設定します(
SET #p.#n = :n, #p.#e = :e)。同じ親の下の兄弟パス同士は重複しません。重複するのはネストだけです。重複を排除します — 各属性が
SET/REMOVE/ADD/DELETE全体でちょうど1つのアクションにだけ登場するようにします。ライブラリの自動フィールドを確認します — 自分の式がすでに書き込んでいる更新では、自動管理される属性(タイムスタンプ、バージョン)を無効にするか除外します。
本当に「親を置き換えてから子を調整する」セマンティクスが必要なら、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 はどちらかを選ぶのではなく拒否するのです。
関連するエラー
- The document path provided is invalid for update — もう1つのネストパスの更新失敗(二重に書かれるのではなく、親が存在しないケース)。
- Invalid UpdateExpression: 構文エラー
- 学習: Update Expression
参考資料
- Using update expressions in DynamoDB — Amazon DynamoDB Developer Guide
- Referring to item attributes when using expressions in DynamoDB — 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 で再現しました — 上記の出力はそのままの逐語です。