Back to core workflows Fix dependency resolution Tune package metadata Validate before publishing

Fixing Corepack Signature Verification Errors

Corepack verifies every package manager it downloads against the npm registry's signing keys. When the registry rotates those keys, older Corepack releases — including the copies bundled with many Node.js versions — no longer recognise the signatures on newly published pnpm and Yarn releases, and every pnpm or yarn command fails before it starts. CI pipelines that worked yesterday stop with a cryptic Cannot find matching keyid error. This guide explains why it happens, the right fix (update Corepack), the stopgaps, and how to make your setup resilient to the next rotation.

Exact symptoms and error messages

The failure happens at the first invocation of the shim, before the package manager runs:

$ pnpm install
/usr/local/lib/node_modules/corepack/dist/lib/corepack.cjs:21535
  if (key == null || signature == null) throw new Error(`Cannot find matching keyid: ${JSON.stringify({ signatures, keys })}`);
                                              ^

Error: Cannot find matching keyid: {"signatures":[{"sig":"MEQCIHGd...","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"keys":[{"expires":null,"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","key":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg=="}]}
    at verifySignature (/usr/local/lib/node_modules/corepack/dist/lib/corepack.cjs:21535:47)

Other variants appear depending on the Corepack version:

Internal Error: Signature does not match
Error: Cannot find matching keyid

The keyid in signatures is the registry's new key; the list in keys is what your Corepack knows. They do not overlap, so verification fails. Nothing is wrong with your repository, lockfile or network. Reinstalling dependencies, clearing the pnpm store or deleting the lockfile will not help, because the failure happens before the package manager itself has even started. Recognising that early saves a lot of wasted debugging.

Root cause analysis

The npm registry signs every package version with an ECDSA key and publishes the corresponding public keys. Corepack does not fetch those keys at runtime — it ships with a copy embedded in its own code, so that a compromised registry cannot also substitute the keys. When the registry rotates to a new key (as it did in early 2025, when the old key expired), packages published after the rotation are signed only with the new key. Any Corepack release built before the rotation cannot verify them. The overall role of Corepack is described in Package Manager Version Management.

Why an old Corepack rejects a new release The registry signs a newly published pnpm with a rotated key; an old Corepack only has the previous key embedded, so verification fails. npm registry Corepack (old) Corepack (updated) fetch pnpm@9.15.4 signed with key B; only key A embedded fetch pnpm@9.15.4 key B embedded: verified
The embedded key list is a deliberate security choice — updating Corepack is how the new key is trusted.

Why does it break suddenly? Because the failure depends on which package manager version you request, not on when you installed Corepack. A pinned version published before the rotation still verifies with the old key; the moment you bump packageManager to a newer release — or Corepack's fallback picks a newer default — verification fails.

Resolution and configuration patch

Resolving a keyid mismatch Prefer updating Corepack; if that is not possible, pin a package manager version signed with the old key or disable signature checks temporarily. Can you update Corepack? npm install -g corepack@latest new keys embedded; verification stays on yes Can you use a setup action instead? Let pnpm/action-setup install bypasses Corepack in CI yes no Must you keep the old Corepack? Pin an older PM version one signed before the rotation yes no COREPACK_INTEGRITY_KEYS=0 temporary only: disables signature checks no
Updating Corepack is the only fix that keeps verification on; the others are stopgaps.

1. Update Corepack (the real fix)

npm install -g corepack@latest
corepack enable
corepack --version
pnpm --version   # now verifies with the new key

On CI runners, add the update step before anything calls pnpm or yarn:

- uses: actions/setup-node@v4
  with: { node-version-file: .nvmrc }
- run: npm install -g corepack@latest && corepack enable
- run: pnpm install --frozen-lockfile

In Docker images:

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

2. Let a setup action provision the package manager in CI

pnpm/action-setup installs pnpm without Corepack, reading packageManager for the version. If Corepack cannot be updated on a runner, removing corepack enable and using the action avoids the problem entirely for CI.

3. Stopgaps

If you cannot update Corepack immediately — for example, a locked-down build image — you have two temporary options. Pin packageManager to a version published before the rotation, which the old key can verify. Or set COREPACK_INTEGRITY_KEYS=0 to disable signature verification:

COREPACK_INTEGRITY_KEYS=0 pnpm install --frozen-lockfile

Disabling verification removes a supply-chain protection. If you must use it, keep the +sha512 hash in packageManager, which Corepack still checks, so a tampered download is still rejected — and remove the variable as soon as the image is updated.

Fixes for signature verification failures Compares updating Corepack, using a setup action, pinning an older version and disabling integrity keys on security, effort and durability. keeps verification effort durable Update Corepack yes one command yes (keep updating) Setup action in CI npm's own checks low yes for CI Pin pre-rotation PM yes low blocks upgrades COREPACK_INTEGRI TY_KEYS=0 no trivial must be removed
Only updating Corepack keeps every protection and survives future rotations with routine updates.

Worked example: a Monday morning CI outage

On a Monday, every pipeline in an organisation fails at pnpm install with Cannot find matching keyid. Nothing in the repositories changed over the weekend, but a Renovate pull request merged on Friday had bumped packageManager from pnpm@9.15.2 to pnpm@9.15.4, a release signed after the registry's rotation, while the runner image's Node.js still bundled an older Corepack. The platform team adds npm install -g corepack@latest to the shared runner setup, rebuilds the base Docker image with the same line, and pipelines recover within the hour. To prevent a repeat, they add Corepack itself to the runner image's automated update schedule and add a canary job that runs corepack pnpm@latest --version daily, which fails early the next time keys change.

Where the embedded keys come from

Corepack's trusted keys live in a small JSON config compiled into each release, mirroring the keys the npm registry publishes at its /-/npm/v1/keys endpoint. Every Corepack release captures the keys current at build time. That design is intentional: if Corepack fetched keys from the same registry it downloads packages from, an attacker who controlled the registry response could supply both a malicious tarball and a matching key. Embedding keys moves trust to the Corepack release itself, which is distributed through Node.js or npm with its own integrity checks.

The cost of that design is that trust has to be refreshed by updating Corepack. For most developers this happens implicitly when they upgrade Node.js; for long-lived CI images and pinned Node.js versions it does not, which is why the failure concentrates in CI. An environment variable, COREPACK_INTEGRITY_KEYS, exists to override the embedded keys: set to 0 it disables verification, and set to a JSON document in the registry's key format it replaces the embedded list — a safer emergency option than disabling checks, because you can supply the registry's current public keys explicitly after verifying them out of band.

Yarn and other package managers

The same failure affects Yarn when installed through Corepack, with the same fix. Yarn Berry projects that still use a checked-in release under .yarn/releases with yarnPath are unaffected by Corepack key rotations for that release — the file is already in the repository — but they lose the integrity guarantees Corepack provides and must update the checked-in file manually. npm itself, when shimmed through corepack enable npm, is subject to the same verification. If a team uses Volta or mise instead of Corepack, those tools apply their own download verification and are not affected by Corepack's embedded key list, though they have their own update cadence to keep in mind.

Making your setup resilient

Key rotations are rare but inevitable, and the defence is to treat Corepack like any other tool that needs updating:

  • Update Corepack in base images and runner setup on a schedule, not only when it breaks.
  • Prefer setup actions that read packageManager in CI, which keeps CI independent of the Corepack copy bundled with Node.js.
  • Keep +sha512 hashes in packageManager; they remain a strong check even in emergency configurations.
  • Remember Node.js 25+ does not bundle Corepack, so installing it from npm becomes the norm — and with it, the latest keys.

CLI validation and debug commands

# Which Corepack is running, and from where?
corepack --version
command -v corepack

# Try fetching the declared version explicitly
corepack install

# Show which keyids this Corepack trusts (look for the embedded keys)
node -e "console.log(require(require('path').join(require('child_process').execSync('npm root -g').toString().trim(),'corepack/package.json')).version)"

# Confirm the environment is not disabling checks
env | grep -i COREPACK_

Frequently Asked Questions

Is this error a sign of a compromised package? Almost never. It means your Corepack does not know the registry's current key. A genuinely tampered tarball would fail with a signature mismatch against a key Corepack does know, or with a hash mismatch against your pinned +sha512 value.

Why does npm itself not fail the same way? npm verifies registry signatures with keys it fetches from the registry at npm audit signatures time, and does not require signature verification for normal installs. Corepack embeds keys deliberately for stronger guarantees, which is why it needs updating after rotations.

Will updating Corepack break older pinned versions? No. New Corepack releases include both the current and previous keys while old signatures remain valid, so previously pinned versions keep verifying.

Why does it fail only on some developers' machines? Developers who upgraded Node.js recently have a newer bundled Corepack with the new keys; those on an older Node.js release do not. Checking corepack --version on a working and a failing machine usually shows the difference immediately.

Does disabling Corepack and installing pnpm globally avoid the problem? It avoids this specific error, but it also removes version pinning unless something else enforces the packageManager field. If you go that way, add engines.pnpm with engine-strict=true so a mismatched global install fails loudly.

Related

Package Manager Version Management