[BUG] overrides for a transitive dependency are dropped when it is reached through a `file:`/workspace link · Issue #9659 · npm/cli · GitHub
Skip to content

[BUG] overrides for a transitive dependency are dropped when it is reached through a file:/workspace link #9659

Description

@manzoorwanijk

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

A root overrides entry that targets a transitive dependency is silently ignored when the path to that dependency crosses a file: (or workspace) link boundary.
The transitive dependency is installed at its original, un-overridden version, and the lockfile records that wrong version.
No warning or error is emitted.

Given a root that depends on a local package via file:, where the local package pulls a registry dependency with its own transitive dependency, an override on the transitive dependency has no effect.

// package.json
{
  "name": "root",
  "version": "1.0.0",
  "dependencies": { "a": "file:./pkgs/a" },
  "overrides": { "brace-expansion": "2.0.1" }
}
// pkgs/a/package.json
{ "name": "a", "version": "1.0.0", "dependencies": { "glob": "7.2.0" } }

After npm install, the lockfile pins brace-expansion@1.1.15 instead of the overridden 2.0.1:

node_modules/brace-expansion => 1.1.15   // WRONG, override ignored

The same wrong result occurs under both install-strategy=hoisted and install-strategy=linked, so this is not specific to the linked strategy.

For contrast, the identical override works when the dependency chain does NOT cross a link boundary.
Declaring glob as a direct dependency of the root (instead of via the file: package) correctly pins brace-expansion@2.0.1.

Expected Behavior

The override should apply regardless of whether the overridden dependency is reached through a file:/workspace link.
brace-expansion should be installed and locked at 2.0.1, matching the behavior when the same dependency is reached without crossing a link boundary, and matching the hoisted/registry-only result.

Steps To Reproduce

  1. Create a project whose package.json declares "dependencies": { "a": "file:./pkgs/a" } and "overrides": { "brace-expansion": "2.0.1" }.
  2. Create pkgs/a/package.json with "dependencies": { "glob": "7.2.0" } (glob pulls minimatch which depends on brace-expansion@^1.1.7).
  3. Run npm install.
  4. Inspect the installed/locked brace-expansion version: it is 1.1.15, not the overridden 2.0.1.
  5. Replace the file: dependency with a direct "glob": "7.2.0" dependency on the root and reinstall: brace-expansion is now correctly 2.0.1.

Environment

  • npm: 12.0.0-pre.1 (latest branch)
  • Node.js: v24.17.0
  • OS Name: macOS (Darwin 25.5.0)
  • System Model Name: Mac17,6
  • npm config:
install-strategy = hoisted   ; also reproduces with linked

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugthing that needs fixingNeeds Triageneeds review for next steps

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions