Cached builds result in MODULE_NOT_FOUND

Every time I build my project using cache: npm it will fail after files are cached.

The error upon failure is:

$ npm ci 
npm WARN prepare removing existing node_modules/ before installation
npm ERR! code MODULE_NOT_FOUND
npm ERR! Cannot find module '../pack.js'
npm ERR! A complete log of this run can be found in:
npm ERR!     /home/travis/.npm/_logs/2019-01-15T21_56_06_702Z-debug.log

One clue is that uncached builds are using npm install whereas builds where the cache already exists will use npm ci.

The configuration I’m using is:

language: node_js
node_js:
- '8.3'
cache: npm
...

(see https://github.com/bobvanderlinden/probot-auto-merge/blob/master/.travis.yml)

My repository has package-lock.json: https://github.com/bobvanderlinden/probot-auto-merge/blob/master/package-lock.json

My latest build of master shows the problem quite well. I’m using multiple stages. The first stage passes and thus generates a cache, but the second one will use the cache and fails. See https://travis-ci.com/bobvanderlinden/probot-auto-merge/builds/97343245

I’ve tried to delete all cache files multiple times and have tried different configuration options, but I thought the current one is the most minimal and simple and I was thinking this should just work according to the documentation. I was about to drop caching altogether, but I thought I first ask here for help.

Does anyone have any idea how to get this working correctly or why it is failing?

It seems to me a combination of things.

First, notice that you are choosing node_js: 8.3 with cache: npm in https://github.com/bobvanderlinden/probot-auto-merge/blob/fbf3335a96e106d079fb3a93c495bf6abe54afe/.travis.yml.

Second, in the initial job, you see that npm version is one that comes with Node.js 8.3.0, which is 5.3.0. This is too old to support npm ci, so the default dependency installation command is npm install.

Third, in the second job, however, npm --version shows 6.5.0. It is not clear to me why. I would imagine that this is because of the use of the cache from the previous job, since on the outset of this job, npm --version clearly shows 5.3.0. The newer version now informs a different installation command npm ci; this would not work because the directory we have cached is npm_modules, whereas it is expecting to find things in $HOME/.npm (because the package-lock.json file exists).

This sort of npm switching is not anticipated by our build script, and it seems too unwieldy to really cope with.

It is not clear to me how best to deal with the problem, as I am not familiar with the Node.js ecosystem and its best practices. However, I can suggest a few potential solutions (in no particular order).

  1. Use a more recent Node.js version. Presumably one that has a recent version of npm that can handle the ci subcommand should behave well. (I don’t know how recent is “recent enough.”)
  2. Update npm in before_install to a version at least 5.8.0. This should ensure consistent install behavior.
  3. Identify the reason that npm 6.5.0 is in use in the second job, and rectify. This, too, should ensure consistent behavior.
  4. Remove package-lock.json from the repository. This should force the use of npm install even when npm is recent enough to handle the ci subcommand.

Not every one of these might work, and they may exhibit different characteristics and benefits (e.g., presumably npm ci is faster than npm install https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable). I suggest working out the solution that works best for you.

Thank you! Upgrading NodeJS to the latest LTS worked for me! :+1:

Great to hear you were able to resolve it.