Repository navigation
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The guard blocks a safely nestable peer, causing a required dependency to be hoisted and turn a failed optional dependency into an ETARGET install failure.
1 open issue
What changed in this PR
This PR addresses #10149 by preserving failed dependency targets during Arborist peer-set loading, preventing repeated replacements that can make installation loop indefinitely.
Changes:
- Skip peer resolution when the existing target is a recorded load failure.
- Add regression coverage for multiple peer dependents, including a transitive peer, across required and optional dependencies in default, strict, and force modes.
| File | Description |
|---|---|
workspaces/arborist/test/arborist/build-ideal-tree.js |
Tests load-error reporting and optional-group handling without looping. |
workspaces/arborist/lib/arborist/build-ideal-tree.js |
Adds a guard to preserve failed targets during peer-set loading. |
Review effort: Balanced
| const existing = node.parent.sourceReference.resolve(edge.name) | ||
| if (this.#loadFailures.has(existing)) { | ||
| continue |
There was a problem hiding this comment.
Please add this mixed required/optional case to the regression tests, asserting both the valid nested peer and the inert optional ancestor across those modes, while retaining the new loop tests.
There was a problem hiding this comment.
Updated in 1697836. The regression covers default, strict, and force modes: the required peer resolves beneath the wrapper, and the failed optional root dependency stays inert. The existing loop tests are unchanged. Both the Arborist and npm CLI suites passed locally.

An unavailable direct dependency can be repeatedly replaced by a valid version requested by a transitive peer. Its original edge then reinstalls the failed, versionless node, so
npm install --package-lock-onlynever reaches the load-error reporting phase.Keep an already failed target in the real tree while loading subsequent peer sets. The existing pruning phase can then report its original
ETARGET, or mark the optional peer-dependent group inert. Valid peer targets continue through the existing resolution path. This does not add an iteration limit or change dependency versions.The regression includes the transitive
react-shallow-rendererpeer from the report, with required and optional dependencies under default, strict and force modes.Validation
ETARGETin 394 ms. The mock-registry regression also timed out before the fix.ETARGETin 671 ms on Node 26.8.1 and 584 ms on Node 24.19.0. The valid-version control succeeds.npm test: all 59 test files pass with 100% statement, branch, function and line coverage, including lint and package template checks (Node 24.19.0). No upstream CI result is claimed here.ae98c62586b6fea44114f72e249e246a2981de70; no tooling changes are included.References
Fixes #10149