fix(config): say what is wrong when a path is keyed and replaced - #16
Merged
Conversation
Configuring keyBy and replace on the same path reported that the replace path "makes the keyBy path unreachable". Nothing is unreachable: the two policies sit on the same node, one saying to enter the list and the other saying it is opaque. They contradict rather than nest, and the old wording sent the reader looking for a nesting problem that is not there. It also withheld the spelling that works, which is not guessable. The message now states the contradiction and names the item-swap spelling. It deliberately stops there rather than prescribing an edit. A first attempt did prescribe one, and both reviewers found configurations where the prescription throws again: a keyBy nested below the list strands under either replace spelling, and a second colliding replace path defeats the advice even with no nested policy. Guaranteeing that a suggested edit compiles would mean solving the whole policy graph inside one error, so the message reports the collision it found and names a spelling, both of which stay true whatever else is configured. Genuinely nested collisions keep the unreachable wording, which is accurate for them. The README documented neither case at the same path, so it does now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Item 3 of the original four flagged design choices. The verdict there was keep the validation, fix the diagnostic.
The defect
keyBy: {"order.items": "id"}withreplace: ["order.items"]threw:Nothing is unreachable. Both policies land on the same node — one says enter the list and reconcile it, the other says the list is opaque. They contradict rather than nest, so the wording sent the reader hunting for a nesting problem that doesn't exist. It also withheld the spelling that works,
replace: ["order.items[]"], which isn't guessable.Now:
Genuinely nested collisions keep the "unreachable" wording, which is accurate for them.
Why it names a spelling instead of prescribing a fix
My first attempt told the caller what to do — "use
items[], or drop the keyBy". Both reviewers independently found configurations where that prescription throws again:keyBynested below the list is stranded under either spellingreplacepath defeats the advice even with no nested policyMy second attempt special-cased the nested policy and claimed it "has to go either way" — also false, since dropping the replace keeps it, and that config is the README's own showcase example.
Two wrong fixes in a row showed the shape was wrong, not the wording. Guaranteeing a suggested edit compiles means solving the whole policy graph inside one error message. So the message reports the collision it found and names a spelling — both true whatever else is configured — and stops. The special-case detection was removed entirely, which is also less code than either failed attempt.
Verification
main, Fable 22,765: zero accept/reject differences, zero error-class differences, 2,882 message changes all of the equal-path shape.isPrefixsucceeds, so it means identical paths — confirmed against unicode, embedded whitespace, control characters, quotes, and 200-segment paths.not.toThrow(/regex/)genuinely inspects the thrown message rather than passing vacuously.125 tests,
vp run checkgreen.Summary by cubic
Clarifies config validation when
keyByandreplacetarget the same path. Old behavior mislabeled the collision as “unreachable”; new behavior reports a contradiction and names the item-swap spelling (path[]). Nested collisions still use “unreachable.”src/paths.ts, equal-path collisions now throw: “path '' cannot be both keyed and replaced…; replacing matched items instead is spelled '
[]'”. Prefix collisions keep the “unreachable” error.
Written for commit 471fcd8. Summary will update on new commits.