npm / npm/cli

[BUG] `npm install` sometimes removes indirect dependencies if a parent node was deleted from the lockfile

Open
#7,746 2 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Needs Triage
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
Current Behavior

My team sometimes deletes nodes from package-lock.json as specific package versions are deleted from our internal registry. Our expectation is that npm install should then install the latest version of that package that satisfies the requirements in package.json, without changing indirect dependencies unnecessarily.

However, we're seeing an issue where npm install sometimes deletes an indirect dependency of the deleted node, even as it replaces that node. We have to run npm install a second time in order to restore the indirect dependency.

This issue only seems to occur when there's a different version of the indirect dependency installed.

Expected Behavior

We expect package-lock.json to always be in a consistent state after an npm install, with all dependencies satisfied.

Steps To Reproduce

I've created a CodeSandbox: https://codesandbox.io/p/devbox/quirky-rain-rv9lkl You can create a new project in the same state by running npm install glob@7.1.6 && npm install minimatch@4.2.3 && npm install mocha@10.7.3.

Once you have that project set up, the steps to replicate the bug are:

  1. Delete the "node_modules/mocha" node from package-lock.json.
  2. Run npm install.
  3. Check the diff and see that npm restored the "node_modules/mocha" node, but removed the "node_modules/mocha/node_modules/brace-expansion" node. That directory has also been deleted from node_modules. This means that mocha's indirect dependency on brace-expansion@^2.0.1 (by way of its dependency on minimatch@^5.1.6) is unsatisfied; mocha would instead use brace-expansion@1.1.11, which is installed at the root of node_modules.
  4. Run npm install again and observe that "node_modules/mocha/node_modules/brace-expansion" has been restored in both package-lock.json and node_modules.
Environment

I've observed this issue in npm v8, v9, and v10.

  • npm: 10.8.2
  • Node.js: 20.16.0
  • OS Name: macOS 14.6.1
  • System Model Name: M1 MacBook Pro
  • npm config:
; node bin location = /Users/trevorburnham/.asdf/installs/nodejs/20.16.0/bin/node
; node version = v20.16.0
; npm local prefix = /Users/trevorburnham/Code/lockfile-with-missing-parent-testcase
; npm version = 10.8.2
; cwd = /Users/trevorburnham/Code/lockfile-with-missing-parent-testcase
; HOME = /Users/trevorburnham

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the linked CodeSandbox or by installing glob@7.1.6, minimatch@4.2.3, and mocha@10.7.3, then delete the node_modules/mocha entry from package-lock.json and run npm install. Compare package-lock.json and node_modules after the first and second installs; done means one install restores mocha without removing its required nested brace-expansion dependency.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.