npm breaks package-lock.json when updating packages with dependencies to several versions of a package

(Mirko Grönroos) #1

What I Wanted to Do

I wanted to update some dependencies to an app.

What Happened Instead

The deps did update, but package-lock.json is now invalid and running npm ci will result in a broken installation.

Reproduction Steps

Create a new package with npm init and follow these steps.

  1. Add Hapi as a dependency: npm i -S hapi@17.3.1. Hapi has a dependency on catbox-memory@3.x.x
  2. Add catbox-memory@4 as a project dependency: npm i -S catbox-memory@4.0.1
  3. Time has passed, update newer version of hapi: npm i -S hapi@17.8.5
  4. Prepare to publish by running npm ci
  5. Hapi is now broken because it depends on catbox-memory@3 which has is missing a dependency. node -e 'require("hapi")' fails with the following error:
module.js:550
    throw err;
    ^

Error: Cannot find module 'big-time'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/npm-deps-bug/node_modules/hapi/node_modules/catbox-memory/lib/index.js:5:17)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)

I created a Gist with a shell script to automatically run the steps above and test where things go wrong.

See https://gist.github.com/hermo/45ff25dc6f6d1eca1795035279388023.

Details

In package-lock.json, hapi 17.8.5 depends on catbox-memory@3.x.x, which is expected.
However the entry for catbox-memory@3.1.4 has no dependencies at all.

Running npm view catbox-memory@3.1.4 dependencies shows that it should require:
{ 'big-time': '2.x.x', boom: '7.x.x', hoek: '6.x.x' }

Running npm ls | grep ERR also detects that the deps for catbox-memory@3.1.4 are not ok:

npm ERR! missing: big-time@2.0.1, required by catbox-memory@3.1.4
npm ERR! missing: isemail@3.x.x, required by joi@14.0.4

There’s also something wrong with ‘joi’ dependency ‘isemail’ but I will disregard that for this report.

Cause of issue

The issue seems to be related to the fact that catbox-memory@4 is a direct dependency of the app while catbox-memory@3 is a dependency of hapi.

Diff between broken and working package-lock.json

"catbox-memory": {
  "version": "3.1.4",
  "resolved": "https://registry.npmjs.org/catbox-memory/-/catbox-memory-3.1.4.tgz",
  "integrity": "sha512-1tDnll066au0HXBSDHS/YQ34MQ2omBsmnA9g/jseyq/M3m7UPrajVtPDZK/rXgikSC1dfjo9Pa+kQ1qcyG2d3g==",
+ "requires": {
+  "big-time": "2.x.x",
+  "boom": "7.x.x",
+  "hoek": "6.x.x"
+ }

When updating hapi and it’s deps, npm seems to be looking at the deps for catbox-memory@4 instead of what is requested by hapi (catbox-memory@3.x.x).

Skipping step 2 (npm i -S catbox-memory@4.0.1`) will prevent the issue from appearing. This is easy to verify by editing test.sh from the Gist and commenting out code for step 2.

Workaround

Running npm i will detect the errors and fix package-lock.json.

Platform Info

$ npm --versions

{ 'npm-deps-bug': '1.0.0',
  npm: '6.9.0',
  ares: '1.10.1-DEV',
  cldr: '32.0',
  http_parser: '2.8.0',
  icu: '60.1',
  modules: '57',
  napi: '4',
  nghttp2: '1.33.0',
  node: '8.16.0',
  openssl: '1.0.2r',
  tz: '2017c',
  unicode: '10.0',
  uv: '1.23.2',
  v8: '6.2.414.77',
  zlib: '1.2.11' }

$ node -p process.platform
darwin