Skip to content

[BUG] install-strategy=linked: Installed transitive optional dependency is not materialized in the actual tree with install-strategy=linked #9627

Closed

Description

@manzoorwanijk

Part of #9608.

Scope: this affects transitive optional dependencies — ones a non-root package depends on, which under linked live as siblings in the store. A root-declared optional dependency works correctly (it is symlinked into the top-level node_modules and loaded as a direct child of the root, so it never relies on the affected code path). This is the general root cause behind the "extension-added optional dep reported UNMET" finding (sweep BUG 15); the trigger there is not the extension but that the optional dep is transitive.

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

Under install-strategy=linked, an optional dependency that is actually installed is missing from the tree that loadActual builds. The package is present on disk — extracted into node_modules/.store, with a valid symlink into its consumer's store node_modules — yet read commands that walk the actual tree do not see it:

  • npm ls reports UNMET OPTIONAL DEPENDENCY fsevents@~2.3.2, even though fsevents is installed.
  • npm sbom omits the package entirely (undercounts components versus hoisted).

Hoisted produces the correct result for the same dependency set (fsevents@2.3.3 shown by ls, present in the SBOM).

This is distinct from the transitive-devDependencies ESBOMPROBLEMS bug (#9610): there the linked tree reported too many required edges; here an installed optionalDependency is reported as unmet/absent (too few).

Expected Behavior

An optional dependency that is installed in the store must appear in the actual tree under install-strategy=linked, identical to the hoisted strategy — npm ls should show it as installed (not UNMET), and npm sbom should include it.

Steps To Reproduce

cd "$(mktemp -d)"
echo 'install-strategy=linked' > .npmrc
cat > package.json <<'EOF'
{ "name": "opt", "version": "1.0.0", "dependencies": { "chokidar": "3.6.0" } }
EOF
npm install >/dev/null

# fsevents IS installed in the store:
ls node_modules/.store | grep fsevents
#   fsevents@2.3.3-...

# ...but the actual tree does not see it:
npm ls --all | grep -i fsevents
#   UNMET OPTIONAL DEPENDENCY fsevents@~2.3.2

npm sbom --sbom-format=cyclonedx | grep -c fsevents
#   0

Works with hoisted strategy (control)

rm -rf node_modules package-lock.json .npmrc
npm install --install-strategy=hoisted >/dev/null
npm ls --all | grep -i fsevents
#   fsevents@2.3.3

Environment

  • npm: 12.0.0-pre.1 (reproduced on latest)
  • Node.js: v24.17.0
  • OS Name: macOS (Darwin 25.5.0)
  • System Model Name: MacBook (arm64)
  • npm config:
install-strategy=linked

Related: #9608, #9610.

Activity

  1. changed the title [-][BUG] install-strategy=linked: Installed transitive optional dependency is not materialized in the actual tree with `install-strategy=linked`[/-] [+][BUG] `install-strategy=linked`: Installed transitive optional dependency is not materialized in the actual tree with `install-strategy=linked`[/+] on Jun 24, 2026
  2. added a commit that references this issue on Jun 25, 2026
    6a5bf26
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions