yarn "Your lockfile needs to be updated" (--frozen-lockfile) - Fix in CI
With --frozen-lockfile (Yarn 1) or --immutable (Yarn Berry), yarn refuses to change yarn.lock. If package.json implies a different lockfile than the committed one, the install fails instead of rewriting it.
What this error means
yarn install --frozen-lockfile (or --immutable) fails in CI saying the lockfile needs to be updated, while a plain yarn install locally would just rewrite yarn.lock. The committed lockfile does not match package.json.
error Your lockfile needs to be updated, but yarn was run with
`--frozen-lockfile`.
# Yarn Berry:
➤ YN0028: The lockfile would have been modified by this install,
which is explicitly forbidden.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.
# 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 lockfileCommon causes
package.json changed without updating yarn.lock
A dependency was added or bumped in package.json but yarn.lock was not regenerated, so the frozen/immutable check sees a mismatch.
yarn.lock not committed
The updated lockfile was left uncommitted, so CI checks out a stale yarn.lock that no longer matches package.json.
How to fix it
Regenerate and commit yarn.lock
Run a normal install locally to update the lockfile, then commit it.
yarn install # updates yarn.lock locally
git add yarn.lock
git commit -m "chore: update yarn.lock"Guard against future drift
- Run
yarn install --immutablein PR checks so drift is caught before merge. - Always commit yarn.lock with the package.json change that caused it.
- Resolve lockfile merge conflicts by regenerating, not hand-editing.
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.
# 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') }}-v2How to prevent it
- Commit yarn.lock alongside every dependency change.
- Use --immutable/--frozen-lockfile in CI to catch drift.
- Regenerate the lockfile to resolve conflicts.