[BUG] `npm ls` flags installed optional peers as extraneous under `install-strategy=linked`
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 10.1k
- Forks
- 4.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 19
Description
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
With install-strategy=linked, a satisfied optional peer is symlinked into the dependent's own node_modules, and npm ls reports that symlink as extraneous. It affects workspaces and store packages alike (seen in a large monorepo on every workspace with an optional @types/react peer). Hoisted is clean, and it started in npm 11.6.3 (11.6.2 is clean).
Expected Behavior
An installed optional peer that the dependent resolves is not extraneous, matching hoisted.
Steps To Reproduce
mkdir x && cd x
mkdir -p packages/a
printf '{"name":"r","version":"1.0.0","workspaces":["packages/*"],"dependencies":{"a":"1.0.0","ws":"8.21.3","utf-8-validate":"6.0.5"}}' > package.json
printf '{"name":"a","version":"1.0.0","peerDependencies":{"utf-8-validate":"^6"},"peerDependenciesMeta":{"utf-8-validate":{"optional":true}}}' > packages/a/package.json
printf 'install-strategy=linked\n' > .npmrc
npm install --ignore-scripts --no-audit --no-fund
npm ls --all
# actual: utf-8-validate@6.0.5 extraneous under both a@1.0.0 and ws@8.21.3
# expected: no extraneous (same as --install-strategy=hoisted)
Environment
- npm: 12.0.2 and
latestsource - Node.js: v24.18.0
- OS Name: macOS Darwin 25.6.0
- npm config:
install-strategy=linked
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided workspace reproduction with npm install --install-strategy=linked and npm ls --all, then compare its output with hoisted installation. Trace how npm ls classifies the symlinked optional peer under the dependent and workspace packages; done means a satisfied optional peer is no longer reported as extraneous in both cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100