Repository navigation
fix(ts): report correct paths for values after nested objects in deepCopyWithValidation - #4981
Conversation
|
Assessment: Approve Clean, well-scoped fix for the stale Review Categories
Nice job pinpointing the root cause and documenting the before/after behavior so clearly. |
|
Thanks for the fix! Using |
…CopyWithValidation The replacer's path stack was pushed for every object/array but never popped, so after a nested subtree finished the stale frame stayed on top and every later sibling was reported under the wrong parent (e.g. `value.nested.bad` instead of `value.bad`, `items[0][1]` instead of `items[1]`). Pop frames for finished subtrees by comparing the replacer's holder (`this`) with the frame's object, so paths resolve against the object currently being serialized.
…validation
The bracket-notation decision looked only at the key, so numeric-string
keys on plain objects were reported as array indices (`{ '0': fn }` as
`value[0]` instead of `value.0`), and the root check `key !== ''` also
swallowed a real empty-string property, hiding its segment from the path
(`{ '': { bad: fn } }` as `value.bad` instead of `value[''].bad`).
Choose bracket notation only when the holder (`this`) is an array, and
distinguish the initial replacer call (empty key, no frames on the
stack) from a real '' property key, which is appended as `['']`.
06b4d2f to
1273ef3
Compare
|
Thanks @opieter-aws for the review, and glad the parent-tracking approach resolves the reported bug! Quick heads-up: upstream history was restarted, so I rebased this branch onto current main ( 1. Numeric-looking keys on plain objects The bracket-notation decision now checks the holder (
2. Real empty-string keys The root check now distinguishes the initial replacer call (empty key, no frames on the stack) from a real
Tests
The original stale-pathStack tests (sibling keys, array elements, and keys after multiple levels of nesting) all still pass, as do the |
|
Assessment: Approve Re-reviewed after the rebase and Verification
Thanks for the thorough follow-up and the extra regression coverage. |
…CopyWithValidation (strands-agents#4981)
Human Overview
Description
deepCopyWithValidationreports the wrong path for any non-serializable value that comes after a nested object or array. The replacer's path stack (strands-ts/src/types/json.ts:74) is pushed on every descent but never popped, so once a nested subtree finishes serialization the stale frame stays on top and every later sibling inherits that finished subtree's path.Users hit this through
StateStorestate validation (strands-ts/src/state-store.ts:92) and router metadata validation (strands-ts/src/models/routing/router.ts:494): storing{ nested: { x: 1 }, bad: fn }under keyais reported asvalue for key "a".nested.badinstead ofvalue for key "a".bad, pointing users at the wrong location. The existing tests only covered single-descent paths, so the sibling case was untested.Each stack frame now carries the object it was pushed for, and the replacer pops frames down to the object currently being serialized, so paths always resolve against the actual parent.
Related Issues
None — small bug fix, no prior issue.
Documentation PR
Not needed — no public API change, only corrected error-message paths.
Type of Change
Bug fix
Testing
hatch run prepareNot run: this PR touches only
strands-ts/; the hatchpreparepipeline coversstrands-py/. The TypeScript gates all pass:npm test— 175 test files, 4891 tests passedbuild,test:coverage,lint,format:check,type-check) — all passedsrc/types/__tests__/json.test.tsfail onmainwith the stale paths (value for key "a".nested.bad,items[0][1],value.first.deep.second.deep.bad) and pass with this changeAdditional Details
Before / after
Checklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.