
pnpm 11 Ignored Your Overrides: Move Config Before CI Rewrites It
pnpm 11 moved project settings out of package.json. Migrate overrides and build policy to pnpm-workspace.yaml before CI rewrites your lockfile.
A dependency override is often security configuration in disguise. You add one to keep a bad transitive version out of the lockfile, then assume the package manager will keep enforcing it. That assumption becomes dangerous during a major upgrade.
pnpm 11 changes where project settings live. If your repository still keeps pnpm configuration inside package.json, treat the upgrade as a configuration migration, not just a version bump. The failure mode can be subtle: install succeeds, the lockfile changes, and the setting you expected to protect the dependency graph is no longer applied.
The symptom: a clean install changes more than you expected
Find the configuration before you upgrade
Start with a repository search. You are looking for pnpm configuration in package.json, workspace-local .npmrc files, and CI environment variables using the old npm_config_ prefix. Do this before regenerating a lockfile so the diff remains an audit trail instead of a mystery.
rg -n '"pnpm"|overrides|patchedDependencies|onlyBuiltDependencies|ignoreDepScripts|npm_config_' \
package.json pnpm-workspace.yaml .npmrc .github 2>/dev/nullDo not copy settings blindly. Some old build-dependency settings were removed and replaced by allowBuilds. Others are workspace-level settings that belong in pnpm-workspace.yaml. Check the v11 migration notes against the settings your repository actually uses.
Move the intent, not just the YAML
A common legacy setup keeps overrides in package.json. In pnpm 11, place the project configuration in the workspace file instead. The exact packages below are placeholders. Preserve your own constraint and review why each override exists before carrying it forward.
// package.json (legacy location)
{
"pnpm": {
"overrides": {
"some-transitive-package@<2.4.0": ">=2.4.0"
}
}
}# pnpm-workspace.yaml
packages:
- '.'
overrides:
some-transitive-package@<2.4.0: '>=2.4.0'
# Add migrated patchedDependencies and other project settings here too.Audit build scripts separately
pnpm 11 removes older build-dependency settings in favor of allowBuilds. This is not a cosmetic rename. Build scripts are part of your supply-chain policy, so write an explicit allow or deny decision for every package that needs one. Do not globally allow scripts just to make an install go green.
# pnpm-workspace.yaml
allowBuilds:
esbuild: true
sharp: true
unwanted-package: falseMake the migration prove itself in CI
The useful check is not “did pnpm install finish?” It is “did the resolved graph and lockfile preserve the policy we intended?” Pin the package-manager version, install with the same command CI uses, and inspect the resulting diff. If an override is important, make its presence in the lockfile or resolved tree an intentional assertion.
# Run with the pnpm 11 version pinned by your repository/toolchain.
pnpm --version
pnpm install --frozen-lockfile
pnpm why some-transitive-package
git diff --exit-code -- pnpm-lock.yamlUse a temporary upgrade branch for the first run. A frozen lockfile should fail if your configuration migration was incomplete, which is better than discovering the discrepancy after an automated dependency update has already rewritten the lockfile.
A short upgrade checklist
1. Pin pnpm 11 and confirm the Node.js 22+ requirement in local development and CI.
2. Move project settings from package.json#pnpm and non-auth .npmrc files into pnpm-workspace.yaml.
3. Convert removed build settings into an explicit allowBuilds policy.
4. Regenerate or validate the lockfile on an isolated branch.
5. Inspect every override, patch, and resolved-version change as a policy change, not routine churn.
6. Keep a small CI assertion for the override that protects the highest-risk dependency.
The pnpm 11 upgrade is worthwhile, but it changes the boundary between application metadata and package-manager policy. Make that boundary explicit. Once configuration lives in the workspace file and CI checks the resulting graph, the next package-manager upgrade becomes a reviewable migration instead of a quiet dependency rollback.