I recently broke our build after doing some seemingly safe NPM operations and decided to look into what happened.
$ uname -mrsv
Darwin 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64
$ node --version
v8.16.0
$ 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' }
Create a new package with npm init
and follow these steps.
- Add Hapi as a dependency:
npm i -S hapi@17.3.1
. Hapi has a dependency oncatbox-memory@3.x.x
- Add catbox-memory@4 as a project dependency:
npm i -S catbox-memory@4.0.1
- Time has passed, update newer version of hapi:
npm i -S hapi@17.8.5
- Prepare to publish by running
npm ci
- Hapi is now broken because it depends on catbox-memory@3:
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)
In package-lock.json, hapi 17.8.5 depends on catbox-memory@3.x.x
, which is OK.
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.
The issue is related to the fact that catbox-memory@4 is a direct dependency of the app while catbox-memory@3 is a dependency of hapi. 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 and commenting out code for step 2.
Running npm i
will detect the errors and fix package-lock.json.
NPM should detect missing dependencies when updating dependencies and keep package-lock.json in order without having to run npm i
to fix things.
Running test.sh
from this Gist in an empty directory will repeat the steps above and stores package.json/package-lock.json for each step.
Sample output from test.sh
is also presented in output.log
.