Ask
97
@tenon_tuesday ·

ERR_PNPM_OUTDATED_LOCKFILE only in ci, lockfile is committed and installs clean locally pnpm

Moved our shared dependency versions into catalog: entries in pnpm-workspace.yaml yesterday. Locally pnpm install is clean, pnpm install --frozen-lockfile is clean, git status is clean, lockfile is committed.

CI dies immediately:

ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile"
because pnpm-lock.yaml is not up to date with packages/api/package.json

Failure reason:
specifiers in the lockfile don't match specs in package.json
* 8 dependencies were added: zod@catalog:, ...

So it thinks 8 dependencies were added, which is exactly the 8 I moved to the catalog. But the lockfile in the repo definitely has them. I have deleted and regenerated the lockfile twice and pushed it, same error both times.

What is CI seeing that I am not?

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @whetstone_wu · yesterday · 3 replies

    Your CI is on a different pnpm major than the one that wrote the lockfile. Catalogs are the fastest way to discover this because an older pnpm does not understand catalog: as a specifier at all, so it reads the lockfile, sees specifiers it cannot reconcile with the package.json, and reports them as added.

    Check it directly - add pnpm --version as the first step of the job. I would bet money it prints a 9.

    Fix, in order:

    1. Put "packageManager": "[email protected]" (or whatever you actually run) in the root package.json.
    2. Enable corepack in CI, or use the setup action with version: left unset so it reads that field instead of installing a default.
    3. Regenerate once with the pinned version and commit.

    The general rule is that the lockfile is a build artifact of a specific tool version. Treating it as version-agnostic works right up until it does not, and catalogs, peer dependency resolution changes and the v9 lockfile format bump are all places where it does not.

    86
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @tenon_tuesday · yesterday

      pnpm 9.15 in CI, 10.13 locally. Pinned via packageManager and it installs. Slightly annoyed the error message describes it as "dependencies were added" when the real problem is "I do not know what catalog: means".

      21
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @packlist_pen · 2d ago

      In fairness it cannot know. From v9's perspective catalog: is just an unresolvable specifier string, so "the package.json wants something the lockfile does not describe" is technically what it observed. Still, a version-mismatch hint in that error would save a lot of people an afternoon.

      18
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @dartfit_dana · yesterday · 2 replies

    Whenever you see this error, read the full body rather than the headline. It names the exact package.json and lists specifiers. The three causes in descending order of frequency:

    • tool version mismatch (yours)
    • somebody hand-edited a package.json and did not re-run install, so the specifier moved from ^3.22.0 to ^3.23.0 with no lockfile change
    • workspace:* vs workspace:^ inconsistency between packages, which changes the recorded specifier even though it resolves to the same local package

    All three show up as "specifiers in the lockfile don't match specs in package.json". The list of names underneath tells you which.

    54
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @durable_ines · 3h ago

      The hand-edited package.json case is worth a pre-commit hook. pnpm install --lockfile-only --frozen-lockfile fails fast if a package.json changed without the lockfile, and it takes under a second because it does not touch node_modules.

      20
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @two_calendars · 20h ago

    Also check .npmrc. Settings that change resolution live there, and a value in your ~/.npmrc that is not in the repo's .npmrc will produce a lockfile CI cannot reproduce. The usual suspects are resolution-mode, save-workspace-protocol, auto-install-peers and shamefully-hoist.

    Rule I follow: every setting that affects resolution goes in the repo-level .npmrc, none of them live in the home directory. If it is not in the repo, CI does not have it.

    33
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @kraut_corner · 3h ago

    Unrelated to your bug but you will hit it next: cache the pnpm store, not node_modules. Caching node_modules in a workspace repo restores symlinks that point at paths that may not exist and produces failures that are much harder to read than this one. pnpm store path gives you the directory to cache.

    19
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @flux_and_solder · 3h ago · 2 replies

    Quickest unblock is to drop --frozen-lockfile in CI and let it regenerate. The lockfile is a suggestion anyway and you get a clean install every time.

    8
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @whetstone_wu · 21h ago

      Please do not. The lockfile is the only thing making your CI build the same tree as your machine. Removing the check does not fix the mismatch, it just means you deploy a different dependency graph than you tested and find out later, in production, on a Friday.

      6
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report