Skip to content
Latchkey

npm lockfileVersion Mismatch in CI - Fix package-lock Version Conflicts

package-lock.json carries a lockfileVersion. When CI runs a different npm major than the one that wrote the lockfile, the tree can churn, warn, or fail to install reproducibly.

What this error means

CI rewrites package-lock.json on every run, prints warnings about an old lockfile, or npm ci complains the lockfile is out of sync because the runner npm reads or writes a different lockfileVersion than your local npm.

npm
npm WARN read-shrinkwrap This version of npm is compatible with
npm WARN read-shrinkwrap lockfileVersion@1, but package-lock.json was
npm WARN read-shrinkwrap generated for lockfileVersion@3. I'll try to do my best.

Diagnose it: reproduce the CI install locally

Install failures are usually environment drift rather than a broken lockfile: a different package-manager major, a different Node version, or a cache that is being restored from a run with different inputs. Reproduce the CI conditions before changing the lockfile, because regenerating it hides the real cause.

Terminal
# match the runner exactly, then install from a clean slate
node --version && npm --version
rm -rf node_modules
npm ci --foreground-scripts

# if that succeeds locally but fails in CI, the difference is the cache
# or the package-manager version, not your lockfile

Common causes

CI npm major differs from the local npm major

npm 6 writes lockfileVersion 1, npm 7+ writes 2, and npm 9+ writes 3; mixing versions across machines makes the lockfile drift.

A regenerated lockfile committed from a different npm

A teammate or tool on another npm version rewrites the lockfile, and CI then disagrees with it.

How to fix it

Pin one npm version everywhere

  1. Choose a single npm major for local and CI.
  2. Install it in CI before running npm ci.
Terminal
npm install -g npm@10
npm ci

Regenerate the lockfile with the pinned version

  1. Delete package-lock.json and reinstall with the chosen npm.
  2. Commit the regenerated lockfile.
Terminal
rm package-lock.json
npm install

Verify the fix survives a cold cache

A green run immediately after a fix often proves nothing, because it restored a cache written before the change. Force a cold install once to confirm the fix is real.

.github/workflows/ci.yml
# temporarily bust the cache key to prove the fix on a cold runner
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: npm
    cache-dependency-path: package-lock.json
# then bump this suffix once, run, and remove it
#   key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}-v2

How to prevent it

  • Pin the npm version via setup-node or packageManager, regenerate the lockfile only with that version, and run npm ci in CI so the lockfile stays authoritative.

Frequently asked questions

What causes npm lockfileVersion mismatch in CI?
There are 2 common causes: ci npm major differs from the local npm major and a regenerated lockfile committed from a different npm. npm 6 writes lockfileVersion 1, npm 7+ writes 2, and npm 9+ writes 3; mixing versions across machines makes the lockfile drift.
How do I fix npm lockfileVersion mismatch in CI?
There are 2 fixes depending on which cause you have: pin one npm version everywhere and regenerate the lockfile with the pinned version. Work through them in order, since the first is the most common.
What does npm lockfileVersion mismatch in CI actually mean?
CI rewrites package-lock.json on every run, prints warnings about an old lockfile, or npm ci complains the lockfile is out of sync because the runner npm reads or writes a different lockfileVersion than your local npm.
How do I stop npm lockfileVersion mismatch in CI happening again?
Pin the npm version via setup-node or packageManager, regenerate the lockfile only with that version, and run npm ci in CI so the lockfile stays authoritative.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card