できない.dev

pnpm install が CI で frozen-lockfile により失敗する(ERR_PNPM_OUTDATED_LOCKFILE)

CI の pnpm は既定で frozen-lockfile になり、pnpm-lock.yaml が package.json と不一致だと失敗する。
ローカルで install してロックファイルを更新・コミットし、pnpm のバージョンを固定するのが本筋。

公開: 更新:

実行例あり(2026-09-04 に実環境で検証)

要約

ERR_PNPM_OUTDATED_LOCKFILE Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with package.json は、CI で pnpm が --frozen-lockfile モードになり、ロックファイルがマニフェストと一致しないため止まった状態。
pnpm は CI を検知すると自動でこのモードになる。
直し方は、ローカルで pnpm install してロックファイルを最新化・コミットし、ローカルと CI の pnpm バージョンを揃えること。

実行例

Corepack で pnpm 9.15.0 を固定した上で、package.json に nanoid を足してロックファイルを更新しないまま --frozen-lockfile を走らせると ERR_PNPM_OUTDATED_LOCKFILE で止まり、ロックファイル側の specifiers と package.json の差分が理由として示される。
通常の pnpm install でロックファイルを更新すると、同じ --frozen-lockfile が「Lockfile is up to date」で通る。

$ corepack enable
$ corepack prepare pnpm@9.15.0 --activate
Preparing pnpm@9.15.0 for immediate activation...
$ pnpm install --no-frozen-lockfile
Progress: resolved 1, reused 0, downloaded 0, added 0
Packages: +1
+
Progress: resolved 1, reused 0, downloaded 1, added 1, done
 
dependencies:
+ ms 2.1.3
 
Done in 503ms
 
   ╭───────────────────────────────────────────────────────────────────╮
   │                                                                   │
   │                Update available! 9.15.0 → 11.25.0.                │
   │   Changelog: https://github.com/pnpm/pnpm/releases/tag/v11.25.0   │
   │         Run "corepack install -g pnpm@11.25.0" to update.         │
   │                                                                   │
   ╰───────────────────────────────────────────────────────────────────╯
$ echo $?
0
$ pnpm install --frozen-lockfile
ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/package.json
 
Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"
 
    Failure reason:
    specifiers in the lockfile ({"ms":"2.1.3"}) don't match specs in package.json ({"ms":"2.1.3","nanoid":"3.3.7"})
$ echo $?
1
$ pnpm install
Progress: resolved 0, reused 1, downloaded 0, added 0
Packages: +1
+
Progress: resolved 2, reused 1, downloaded 1, added 1, done
 
dependencies:
+ nanoid 3.3.7 (6.0.1 is available)
 
Done in 418ms
$ echo $?
0
$ pnpm install --frozen-lockfile
Lockfile is up to date, resolution step is skipped
Already up to date
 
Done in 291ms
$ echo $?
0

— 2026-09-04 時点の出力

検証環境

検証日
実行環境
node:20Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. ロックファイル未更新: package.json の依存を変えたのに pnpm install を流さず、pnpm-lock.yaml が古いまま。
  2. コミット漏れ: ロックファイルが .gitignore に入っている、または add し忘れていて CI に届いていない。
  3. バージョン差: ローカルが pnpm 8、CI が pnpm 9 などでロックファイルの形式が変わり不一致になる。
  4. 手書き編集: 依存やバージョンを手で書き換え、ロックファイルと整合しなくなった。

解決策

1. ロックファイルを更新してコミットする

ローカルで install し直し、差分が出たロックファイルを必ずコミットする。

pnpm install
git add pnpm-lock.yaml
git commit -m "chore: update pnpm-lock.yaml"

CI が frozen-lockfile になるのは仕様で、ロックファイルが最新ならそのまま通る(pnpm install(新しいタブで開く))。

2. pnpm のバージョンを固定する

ローカルと CI で同じメジャーを使う。package.json に宣言しておく。

{
  "packageManager": "pnpm@9.15.0"
}

CI では Corepack で同じバージョンを有効化する(Continuous Integration(新しいタブで開く))。

corepack enable
corepack prepare pnpm@9.15.0 --activate
pnpm install

3. ロックファイルが commit される設定か確認する

.gitignore に pnpm-lock.yaml が紛れていないかを見る。
CI のチェックアウトに含まれていなければ frozen は必ず失敗する。

git check-ignore pnpm-lock.yaml   # 何も出なければ追跡対象

この記事は役立ちましたか?