Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
When a workspace declares a file: dependency that points to a non-workspace local package (a directory outside the project's workspaces globs) and the project is installed with install-strategy=linked, the dependency is silently skipped. npm install reports up to date / added 0 packages, no node_modules entry is created for the dep, and the workspace cannot resolve it at runtime (require throws MODULE_NOT_FOUND). No error or warning is printed.
The key trigger is that the file: target is not itself a workspace. A workspace file: dep that points to another workspace (e.g. "@scope/b": "file:../b" where b is under packages/* — the common monorepo case, e.g. Gutenberg) works fine, because the target is matched by n.isWorkspace. The bug only surfaces for file: targets outside the workspace set — which is exactly the #9115 case (npm --workspace=<ws> link <external-path>), and any workspace depending on a local non-workspace folder.
This is also distinct from the already-fixed #9166 / #9210 (which crashed with ENOENT for file: deps in a non-workspace project). Those now work; this is the residual case where the consumer is a workspace and the target is not.
So install-strategy=linked is not a viable workaround for #9115.
What works vs what fails (linked strategy)
| Scenario |
Result |
Workspace file: dep → non-workspace local package |
❌ silently skipped (not installed, no error) |
Workspace file: dep → another workspace (e.g. Gutenberg file:../i18n) |
✅ installed + resolves |
Root-declared file: dep (workspaces present, any target) |
✅ installed + resolves |
file: dep declared by root in a non-workspace project |
✅ installed + resolves |
| Registry dep declared by a workspace |
✅ installed into node_modules/.store + symlinked into the workspace |
Expected Behavior
A file: dependency declared by a workspace should be symlinked into that workspace's node_modules under install-strategy=linked, identical to a registry dependency and identical to the hoisted strategy. If it genuinely cannot be installed, npm must error — not silently report success.
Steps To Reproduce
rm -rf /tmp/repro9115 && mkdir -p /tmp/repro9115/packages/ws-a /tmp/repro9115/local-dep
cat > /tmp/repro9115/package.json << 'EOF'
{ "name": "mono", "version": "1.0.0", "workspaces": ["packages/*"] }
EOF
cat > /tmp/repro9115/local-dep/package.json << 'EOF'
{ "name": "local-dep", "version": "1.0.0" }
EOF
cat > /tmp/repro9115/packages/ws-a/package.json << 'EOF'
{ "name": "ws-a", "version": "1.0.0", "dependencies": { "local-dep": "file:../../local-dep" } }
EOF
cd /tmp/repro9115
npm install --install-strategy=linked
# => "up to date, audited 5 packages" — but nothing is installed
find . -type d -name node_modules # => (no node_modules at all)
node -e "require.resolve('local-dep/package.json', { paths: ['/tmp/repro9115/packages/ws-a'] })"
# => Error: Cannot find module 'local-dep/package.json'
Works with hoisted strategy (control)
rm -rf /tmp/repro9115/node_modules /tmp/repro9115/package-lock.json
cd /tmp/repro9115
npm install
node -e "console.log(require.resolve('local-dep/package.json', { paths: ['/tmp/repro9115/packages/ws-a'] }))"
# => /private/tmp/repro9115/local-dep/package.json
Environment
- npm: 12.0.0-pre.1 (reproduced on
latest; line unchanged across recent branches)
- Node.js: v24.17.0
- OS Name: macOS (Darwin 25.5.0)
- npm config:
Related: #9115, #9166, #9210.
Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
When a workspace declares a
file:dependency that points to a non-workspace local package (a directory outside the project'sworkspacesglobs) and the project is installed withinstall-strategy=linked, the dependency is silently skipped.npm installreportsup to date/added 0 packages, nonode_modulesentry is created for the dep, and the workspace cannot resolve it at runtime (requirethrowsMODULE_NOT_FOUND). No error or warning is printed.The key trigger is that the
file:target is not itself a workspace. A workspacefile:dep that points to another workspace (e.g."@scope/b": "file:../b"wherebis underpackages/*— the common monorepo case, e.g. Gutenberg) works fine, because the target is matched byn.isWorkspace. The bug only surfaces forfile:targets outside the workspace set — which is exactly the #9115 case (npm --workspace=<ws> link <external-path>), and any workspace depending on a local non-workspace folder.This is also distinct from the already-fixed #9166 / #9210 (which crashed with
ENOENTforfile:deps in a non-workspace project). Those now work; this is the residual case where the consumer is a workspace and the target is not.So
install-strategy=linkedis not a viable workaround for #9115.What works vs what fails (linked strategy)
file:dep → non-workspace local packagefile:dep → another workspace (e.g. Gutenbergfile:../i18n)file:dep (workspaces present, any target)file:dep declared by root in a non-workspace projectnode_modules/.store+ symlinked into the workspaceExpected Behavior
A
file:dependency declared by a workspace should be symlinked into that workspace'snode_modulesunderinstall-strategy=linked, identical to a registry dependency and identical to the hoisted strategy. If it genuinely cannot be installed, npm must error — not silently report success.Steps To Reproduce
Works with hoisted strategy (control)
Environment
latest; line unchanged across recent branches)install-strategy=linkedRelated: #9115, #9166, #9210.