できない.dev

Corepack で「Cannot find matching keyid」が出て pnpm を起動できない

0.31.0 より古い Corepack は npm レジストリの新しい署名鍵を持っておらず、2025 年 1 月下旬以降に公開された pnpm の署名を検証できずに止まる。
Corepack を更新するか、packageManager をハッシュ付きで書く。

公開:

要約

Corepack 経由で pnpm を呼ぶと、pnpm が起動する前に次の例外で終了する。corepack enable 済みの環境で、packageManager を書いたプロジェクトの中から pnpm を実行した場合も同じだ。

Error: Cannot find matching keyid: {"signatures":[{"sig":"MEUCIE…","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"keys":[{"expires":null,"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",…}]}
    at verifySignature (/usr/local/lib/node_modules/corepack/dist/lib/corepack.cjs:21535:47)

Corepack は、ダウンロードした pnpm の署名を自分が持っている npm レジストリの公開鍵で検証してから実行する。
npm レジストリは 2025 年 1 月に署名鍵を切り替えており、公開鍵の一覧(https://registry.npmjs.org/-/npm/v1/keys)では旧鍵 SHA256:jl3bw… の有効期限が 2025-01-29 になっている。
新しい鍵 SHA256:DhQ8w… は Corepack 0.31.0(2025-01-27)の変更履歴(新しいタブで開く)にある「update npm registry keys」で追加されたので、それより古い Corepack は新しい鍵で署名された版を検証できない。
メッセージの signatures 側の keyid が、keys(Corepack が知っている鍵)に見つからないという意味だ。

Node.js 20.18.0 の公式イメージ(同梱の Corepack は 0.29.3)で試すと、pnpm 9.15.0 と 10.0.0 は起動し、9.15.5 と 10.18.0 でこのエラーになった。

解決策

1. Corepack を更新する

corepack enable の前に、npm で Corepack 自体を入れ直す。

npm install -g corepack@latest
corepack --version   # 0.31.0 以上になっていることを確かめる
corepack enable

Dockerfile なら次のように 1 行にまとめる。
CI でも corepack enable を実行しているステップの前に同じコマンドを足せばよい。

FROM node:20.18.0-bookworm-slim
RUN npm install -g corepack@latest && corepack enable

Node.js 25 以降は Corepack が同梱されず npm install -g corepack で入れるため、この問題は起きにくい。

2. Node.js を上げる

Node.js 20.19.0・22.14.0 以降には 0.31.0 以降の Corepack が同梱されている。
パッチバージョンまで固定している指定を見直す。

3. packageManager をハッシュ付きにする

新しい Corepack で corepack use を実行すると、packageManager にハッシュ付きの指定が書き込まれる。

corepack use pnpm@10.18.0
{
  "packageManager": "pnpm@10.18.0+sha512.e804f889f1cecc40d572db084eec3e48…"
}

ハッシュ付きの指定では、Corepack 0.29.3 でも署名の検証で止まらず、ハッシュで照合して pnpm 10.18.0 を起動できた。README(新しいタブで開く) もハッシュの付与をセキュリティ上の理由で強く勧めている。

検証を切るのは最後の手段

環境変数 COREPACK_INTEGRITY_KEYS=0 を設定すると、Corepack は署名の検証を飛ばす。
エラーは消えるが改ざんを検出できなくなるので、Corepack を更新するまでの一時しのぎにとどめる。

よくある原因

  1. Corepack が古い: Corepack は Node.js に同梱された版がそのまま使われるので、Node.js を上げない限り鍵も古いままになる。
  2. 古い Node.js を固定している: CI の Node.js のバージョン指定や Dockerfile の FROM node:20.18.0-bookworm-slim のようにパッチまで固定していると、古い Corepack を使い続ける。
    公式イメージで確かめた同梱版は、20.18.0 が 0.29.3、22.13.1 が 0.30.0、20.19.0 と 22.14.0 が 0.31.0 だった。
  3. 新しい鍵で署名された版を指定している: packageManager に pnpm@10.18.0 のようにハッシュ無しで書くと、Corepack は署名を検証しにいく。

この手順で直った?