Skip to content

[BUG] Overrides ignored for transitive dependencies with install-strategy=linked #9197

@manzoorwanijk

Description

@manzoorwanijk

Found while testing overrides in WordPress/gutenberg. We're switching to strict-peer-deps after adopting the linked strategy.

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

Current Behavior

Somewhat related to #9109

When using install-strategy=linked, npm overrides for transitive dependencies are ignored. The overridden version is installed but the parent's edge still expects the lockfile version, marking the overridden package as invalid. With strict-peer-deps=true, this causes an ERESOLVE error and the install fails completely.

With the default hoisted strategy, the same overrides work correctly — the overridden packages are installed and marked as overridden in the tree.

Expected Behavior

Overrides should work the same way regardless of install strategy. The overridden version should satisfy the parent's dependency edge, just like it does with hoisted.

Steps To Reproduce

Setup (common to both strategies)

rm -rf /tmp/npm-override-bug
mkdir -p /tmp/npm-override-bug
cd /tmp/npm-override-bug

cat > package.json << 'EOF'
{
  "name": "override-bug-repro",
  "version": "1.0.0",
  "private": true,
  "devDependencies": {
    "typescript": "5.8.3",
    "@typescript-eslint/utils": "8.51.0"
  }
}
EOF

With linked strategy (BUG)

echo 'install-strategy=linked' > .npmrc

# 1. Install to create lockfile with 8.51.0 versions
npm install

# 2. Upgrade to TS 6 and add overrides for transitive deps
cat > package.json << 'EOF'
{
  "name": "override-bug-repro",
  "version": "1.0.0",
  "private": true,
  "devDependencies": {
    "typescript": "6.0.2",
    "@typescript-eslint/utils": "8.51.0"
  },
  "overrides": {
    "@typescript-eslint/typescript-estree": "8.58.0",
    "@typescript-eslint/project-service": "8.58.0"
  }
}
EOF

# 3. Reinstall — override is applied but tree is invalid
npm install
npm ls @typescript-eslint/typescript-estree
# Actual:   @typescript-eslint/typescript-estree@8.58.0 invalid: "8.51.0"
# Expected: @typescript-eslint/typescript-estree@8.58.0 overridden

With hoisted strategy (WORKS)

rm -rf /tmp/npm-override-bug
mkdir -p /tmp/npm-override-bug
cd /tmp/npm-override-bug
# ... same setup as above, without the .npmrc ...
npm install
# ... same package.json change as above ...
npm install
npm ls @typescript-eslint/typescript-estree
# @typescript-eslint/typescript-estree@8.58.0 overridden  ✓

With strict-peer-deps=true

Adding strict-peer-deps=true to the .npmrc makes it worse — step 3 fails outright with ERESOLVE, and the override is completely ignored:

npm error ERESOLVE could not resolve
npm error While resolving: @typescript-eslint/project-service@8.51.0
npm error Found: typescript@6.0.2
npm error Could not resolve dependency:
npm error peer typescript@">=4.8.4 <6.0.0" from @typescript-eslint/project-service@8.51.0

Cleanup

rm -rf /tmp/npm-override-bug

Root Cause Analysis

During loadVirtual in load-virtual.js, nodes loaded from the lockfile are created without override context. When the linked strategy builds the tree, override propagation through parent edges doesn't properly update the edge's expected spec, so the overridden version is treated as invalid rather than overridden.

In hoisted mode, when an invalid edge is detected after loading the virtual tree, it gets queued for re-resolution in #initTree (build-ideal-tree.js ~line 340). The linked strategy appears to handle these differently, skipping re-resolution for overridden transitive deps.

Environment

  • npm: v11.12.1 (fork, latest branch)
  • Node.js: v24.14.0
  • OS: macOS (Darwin 25.4.0)
  • npm config:
    install-strategy=linked
    strict-peer-deps=true  ; (optional, makes it worse)

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