ADR-0048: pnpm 12.7.0 and an explicit build policy
Status: Accepted
Date: 2026-09-28
Context
ADR-0026 decided to move to pnpm 11 and to make
pnpm-workspace.yaml the only home for pnpm settings. The move was recorded but never applied:
package.json still pinned [email protected] and carried the pnpm block (overrides,
onlyBuiltDependencies, peerDependencyRules), .npmrc still carried autoInstallPeers and the
hoist patterns, and eight Dockerfiles still pinned 10.27.0 or 10.30.3.
That ADR rejected [email protected] because pnpm 12 was a week old, had not become the latest
dist-tag, and removed install flags without documenting them. Both facts have changed: pnpm 12 is the latest dist-tag (12.6.0 when this was
written), and its release notes list the breaking changes. Those that reach this
repository are the ones pnpm 11 already made, plus new failures that pnpm 10 did not have: unreviewed build scripts, an implicit install before
pnpm exec, and the process-group bug below.
Decision
Pin [email protected] everywhere the version appears: package.json, the setup-node-pnpm composite
action, and every Dockerfile. Apply the settings move that ADR-0026 decided: overrides,
allowBuilds, peerDependencyRules, nodeLinker, autoInstallPeers and publicHoistPattern
live in pnpm-workspace.yaml, and the pnpm block is removed from package.json. ADR-0026's
decision about where settings live stands. Only its pinned version is superseded.
allowBuilds is a complete policy. pnpm 12 fails the whole install with
ERR_PNPM_IGNORED_BUILDS when a dependency has a build script that the policy neither allows nor
denies. lmdb and nx were never built under pnpm 10, so they are set to false. A new
dependency with a build script must be added to the map with a deliberate true or false.
verifyDepsBeforeRun is false. pnpm 11 changed its default to install, so pnpm exec and
pnpm run re-install when node_modules looks stale. The Dockerfile stages that copy only part of
the workspace then pruned nearly every package and failed in the root postinstall, whose scripts/
directory is not in that stage. false is the pnpm 10 behavior.
turbo.json's globalDependencies lists pnpm-workspace.yaml next to .npmrc, so a cache is not
reused across a change to overrides or allowBuilds.
.npmrc is kept for now. This change could not inspect it, so it does not delete it. Its pnpm
settings are inert under pnpm 12 and duplicated in pnpm-workspace.yaml. It can go once someone
has confirmed that it holds nothing but those settings.
Consequences
- pnpm 11 also raised
minimumReleaseAgeto one day. A re-resolution will not pick up a version published in the last 24 hours. The existing lockfile is unaffected. - The first install with pnpm 12 in an existing checkout rebuilds
node_modules. In a non-TTY context that aborts withERR_PNPM_ABORTED_REMOVE_MODULES_DIRunlessCIis set. pnpm-lock.yamlgains a leading YAML document (packageManagerDependencies) that records the pinned pnpm. The rest of the lockfile is unchanged, and a frozen install accepted it. That is the check that the movedoverridesand settings match.- pnpm 12 rejects an unknown key in
pnpm-workspace.yaml(ERR_PNPM_UNRECOGNIZED_WORKSPACE_SETTINGS) when the pinned version is honored, so a misspelled setting now fails instead of being ignored. pnpm install --frozen-lockfile falseis no longer accepted. Use--no-frozen-lockfile.- The
pnpmblock inpackage.jsonand pnpm settings in.npmrcdo nothing. There is no mechanical guard against adding them again.
Why 12.7.0 and not 12.6.0
12.6.0 was the latest dist-tag when this was written, but it has a bug that hangs the e2e jobs. A
script started by pnpm dev ran in its own process group. When Playwright's webServer killed
pnpm's group, next dev and vite dev survived and held the output pipes open, so
playwright test never returned: web-player and web-artists e2e ran 22 to 30 minutes instead of
6 to 8 until they were cancelled (pnpm#15555). 12.7.0
ends the script with pnpm. A local kill-the-group check showed next left running under 12.6.0 and
gone under 12.7.0.
Alternatives considered
[email protected], as ADR-0026 decided — not chosen. It needs the same settings move and the sameallowBuildspolicy, and it is no longer the current release.- Stay on
[email protected]— not chosen: the version drift acrosspackage.json, CI and containers is a correctness problem regardless of the major version. - Bump the version without moving the settings — rejected for the reason ADR-0026 gives: the
install stays green while
overridesandallowBuildsare silently inert.