Skip to content

UpdateItem: SET a.b = :b, a[0] = :z answers the invalid-path text; the service refuses the two paths as conflicting #811

Open

Description

@LeeroyHannigan

An UpdateExpression whose paths name one element once as a map member and once as a list element, such as SET a.b = :b, a[0] = :z, is refused by the service with Two document paths conflict with each other. ExtendDB has no check that compares the paths of one expression with each other. It applies the actions to the item, and the action that does not fit the stored value fails with The document path provided in the update expression is invalid for update. ExtendDB gives that answer when a is a map, a list or absent, and for a key with no item.

Measured against Amazon DynamoDB in us-east-1 on 3 November 2026, one request. Table pk S HASH; item m holds a = {"M": {"b": {"N": "0"}}}; :b = {"N": "1"} and :z = {"N": "2"}. ExtendDB answers are from main eaf16e89e (SQLite, debug build), one request per row.

Request DynamoDB ExtendDB main eaf16e89e (SQLite)
SET a.b = :b, a[0] = :z on item m ValidationException: 1 validation error detected: Invalid UpdateExpression: Two document paths conflict with each other; must remove or rewrite one of these paths; path one: [a, b], path two: [a, [0]] ValidationException: The document path provided in the update expression is invalid for update
SET a[0] = :z, a.b = :b on item m not sent the invalid-path text above
both orders on an item whose a is {"L": [{"N": "0"}]}, on an item without a, and on a key with no item not sent the invalid-path text above, for all six requests

The same statements in a PartiQL UPDATE were measured on the same day. There the service answers the conflict text when a is a map, a list or absent, and for a key with no item, so it checks the paths before it reads the item. In the PartiQL answers the later assignment is path one; in the UpdateItem answer above it is the earlier one.

Where the answer comes from

handle_update_item (crates/engine/src/update_item.rs, line 167) parses the expression through parse_update_expr. parse_update (crates/core/src/expression/update_parser.rs, line 29) returns the SET, REMOVE, ADD and DELETE actions in order and does not compare their paths. The storage layer applies the actions with apply_update (crates/core/src/expression/update_evaluator.rs, line 26). There set_nested (line 507) refuses a[0] on a map and a.b on a list with the invalid-path text (line 526), and set_path (line 478) refuses a nested path whose top-level attribute is missing (line 497), which is the answer for the item without a and for the key with no item.

Not measured

The service's UpdateItem answers for the swapped order and for the other three item states, and the same shapes in TransactWriteItems.

Related

#399 adds the service's overlap rule for update expressions: two paths overlap when one is a prefix of the other. a.b and a[0] are not prefixes of each other, so that rule passes this expression on to the storage layer. The last comment on #108 lists overlapping update paths among the differences still open on main. #411 refuses overlapping paths in its PartiQL UPDATE and has no conflict check.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions