Skip to content
Fran Gonzalez
← Back to blog
(updated Jun 27, 2026)·Clanker·3 min read

corepack packagemanager drifts from mise.toml under renovate

Renovate updates mise.toml via the mise manager and packageManager via the npm manager. They land in different PRs. I treated that as defense-in-depth until they disagreed.

Some matmuls wrote this slop, sorry. My goal with this content is to document some work I (a real human bean) do while poking the Clanker, and try to learn something along the way.

I had pmOnFail: error enforcing a Corepack packageManager field that mirrored the pnpm pin in mise.toml. Renovate bumped mise.toml to pnpm 11.8.0 in a PR separate from the packageManager bump. pnpm aborted CI: “configured to use 11.7.0 of pnpm. Your current pnpm is v11.8.0.”

What I Learned

The Corepack packageManager field and the pnpm entry in mise.toml are two sources of truth for the same version. The pnpm pmOnFail setting enforces the field by aborting the install when the running pnpm does not match. The whole setup reads as defense-in-depth: two independent pins, one exact-version enforcement.

The defense fails when two Renovate managers update the two pins. Renovate’s mise manager updates mise.toml. The npm manager updates the packageManager and engines fields in package.json. They live in different groups and different PRs. Until both land, the field and the running pnpm disagree. pmOnFail: error turns that disagreement into a CI failure.

You can patch the symptom with a Renovate rule that updates the packageManager field in the same group as the mise bump, or one that disables the engines and packageManager updates entirely. Both options add Renovate config to keep the two pins in sync, leaving the drift class in place behind the coordination rule.

The structural fix is to drop the duplicate. Remove the packageManager field from package.json, remove pmOnFail: error from pnpm-workspace.yaml, and rely on mise.toml plus mise.lock (MISE_LOCKED=1) as the sole enforcer. engineStrict: true catches the legitimate cases the duplicate was meant to catch by guarding engines.pnpm: ">=11.7.0 <12", a range rather than an exact pin. Drop the field once you have committed to mise: Corepack stops shipping with Node.js 25, and the pnpm install in CI and Dagger runs through mise shims regardless of what the field says.

The full failure trace and the architectural pattern are in the supply-chain mise and pnpm post, which now carries a warning at the pmOnFail section. The mise-as-sole-source-of-truth thesis is in the self-contained-mise post, now updated to cover the Corepack field.

A second failure path: exact engines pins

Separate from pmOnFail, exact engines pins cause a different failure. When engines.pnpm: "11.7.0" is an exact pin rather than a range, the running pnpm (11.8.0) triggers ERR_PNPM_UNSUPPORTED_ENGINE through engineStrict. This fires even when packageManager has been updated to match and pmOnFail is removed entirely.

Renovate’s artifact update step runs in its own environment with whatever tool versions are available. If that environment has pnpm 11.8.0 and a sub-package’s engines.pnpm says "11.7.0", pnpm refuses to start, and the lockfile update fails. The same applies to engines.node: an exact pin like "26.1.0" in a workspace sub-package breaks when Renovate’s Node is v26.4.0.

The fix follows the same structural principle: use ranges, not exact pins, in engines. ">=11.7.0 <12" for pnpm and ">=26.1.0 <27" for Node match the root package.json convention and survive Renovate’s environment drift.

References

This post was written with AI assistance.