Skip to content

[BUG] npm install <pkg> on an existing lockfile prunes a nested optional peer and leaves its edge invalid #10086

Open

Description

@HardMax71

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

This is not just a request to bump a dependency for a CVE

  • This is not solely a request to bump a dependency for a CVE

Current Behavior

When a package is added or updated against an existing lockfile, and one of its new dependencies has an optional peer that conflicts with a version already hoisted at the root, npm writes a lockfile with an invalid peerOptional edge.

During placement npm does the right thing: it nests the dependency together with a copy of the optional peer that satisfies the range. Then #fixDepFlags prunes that copy. calcDepFlags keeps nodes reachable only through a peerOptional edge extraneous, and #idealTreePrune runs because the tree was loaded from a lockfile and mutated. Afterwards the nested dependency resolves the optional peer to the hoisted version, which does not satisfy it.

Real example: jsdom@30 pulls in @exodus/bytes, which has an optional peer @noble/hashes@"^1.8.0 || ^2.0.0", while selfsigned (via pkijs@3.4.0) needs @noble/hashes@1.4.0 exactly. The silly log shows placeDep node_modules/jsdom @noble/hashes@2.3.0 OK for: @exodus/bytes@1.15.1, but that copy is gone from the saved lockfile:

A fresh install of the same package.json without a lockfile skips the prune and ends up valid. #4859 (fixed in 11.10.1) covered the fresh-install path only. #9249 comes from the same prune of extraneous optional peers; there the edge ends up missing, here it ends up pointing at a version that does not satisfy it.

Expected Behavior

The nested copy of the optional peer stays, so the lockfile is valid and npm ls reports nothing invalid.

Steps To Reproduce

--before pins pkijs to 3.4.0, which has the exact @noble/hashes@1.4.0 dependency:

mkdir repro && cd repro
echo '{"name":"r","private":true,"devDependencies":{"jsdom":"26.1.0","selfsigned":"5.5.0"}}' > package.json
O="--package-lock-only --no-audit --no-fund --ignore-scripts --before=2026-08-15"
npm install $O
npm install $O --save-exact jsdom@30.0.1
npm ls --package-lock-only @noble/hashes      # invalid edges, ELSPROBLEMS
npm ci --ignore-scripts                        # passes
rm -rf node_modules && npx -y npm@10 ci --ignore-scripts   # Missing: @noble/hashes@2.4.0 from lock file

Environment

  • npm: 12.1.0 and 11.20.0, also current main (b317f16)
  • Node.js: 26.0.0
  • OS Name: macOS 26.5
  • System Model Name: MacBook Pro (Apple Silicon)
  • npm config:
; defaults, no .npmrc

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

    Priority 2secondary priority issuews:arboristRelated to the arborist workspace

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions