Hook
pnpm 11.1.3 changed more than fresh resolution. pnpm install now re-validates an existing pnpm-lock.yaml against active policy before any tarball is fetched.
That matters for teams that already added minimumReleaseAge or trustPolicy: no-downgrade and assumed the install-flow was protected. If a lockfile came from an older environment, a CI cache, or another branch, pnpm may now stop the pipeline.
Problem / Context
Until now, enabling policy could look cleaner than it really was. A team could add this to pnpm-workspace.yaml:
minimumReleaseAge: 1440
trustPolicy: no-downgrade
New resolutions became more careful. But an old lockfile could already contain a version that the new policy would not have selected during an honest resolution. Or the lockfile was produced in an environment without those rules, committed to the repository, and then installed in CI with pnpm install —frozen-lockfile.
pnpm 11.1.3 closes that gap. Before downloading a package tarball, pnpm checks lockfile entries against the current minimumReleaseAge and trustPolicy: no-downgrade rules. If an entry violates policy, install fails with one of these ERR codes:
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION;ERR_PNPM_TRUST_DOWNGRADE;ERR_PNPM_LOCKFILE_RESOLUTION_VERIFICATION, when both checks fail in the same batch;ERR_PNPM_NO_MATURE_MATCHING_VERSION, when strict mode cannot find an old-enough version.
The useful part is not that CI may become red. The useful part is that the failure shows a real mismatch between your policy and the actual lockfile. That is better than silently installing a suspiciously fresh or trust-downgraded package.
Why It Matters
Supply-chain protection only works when it sits on the real dependency installation path. If policy is checked only during new resolution, but not during lockfile install, the team has a nice config and incomplete protection.
Common places where this hurts:
- CI restores an old lockfile or pnpm store from cache;
- Renovate or Dependabot opens a PR with a very fresh package version;
- a developer has a different pnpm version locally and pushes the lockfile;
- a monorepo updates dependencies only in one workspace;
- a release pipeline runs
—frozen-lockfileand does not expect policy to inspect the existing lockfile; - a private registry or mirror has incomplete metadata.
For a small side project, this may be just a failed install. For a team with a release window, it becomes an operational risk: dependency policy starts working at the worst possible time because nobody tested it deliberately.
How To Do It
1. Pin the pnpm version
Start by checking that local development and CI use the same major version:
pnpm -v
corepack pnpm -v
If your package.json has packageManager, make sure Corepack uses the expected version:
{
"packageManager": "pnpm@11.1.3"
}
You do not have to rush every project to 11.1.3 immediately, but policy rollout should be tested with the same version that will later run in CI. Otherwise you are testing a pleasant approximation, not the future behavior.
2. Inspect the current policy
Open pnpm-workspace.yaml:
minimumReleaseAge: 1440
minimumReleaseAgeStrict: true
trustPolicy: no-downgrade
minimumReleaseAge sets the delay after a package is published. In pnpm 11, the built-in default is already 1440 minutes, but strict behavior is the important detail. If you explicitly configure minimumReleaseAge, minimumReleaseAgeStrict defaults to strict. If you only rely on the built-in default, behavior is looser for compatibility.
Practical guidance:
- use strict behavior for release-critical CI;
- start with loose behavior for local developer bootstrap if the team is not ready for a hard rollout yet;
- in a monorepo, document any difference between local and CI policy so people understand why CI is stricter.
3. Run a clean frozen install
The minimal smoke test is:
rm -rf node_modules
pnpm store prune
pnpm install --frozen-lockfile
In CI, make this a separate manual job without an aggressive cache restore. If it fails, you want the real reason, not a debate with stale cache state:
name: pnpm-policy-smoke
on:
workflow_dispatch:
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: corepack enable
- run: pnpm install --frozen-lockfile
If policy is active, this job checks not only future dependency updates but also the current lockfile. That is the pnpm 11.1.3 change you are validating.
4. Read errors calmly
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION means the lockfile points to a package that has not passed your age policy yet. It is not always an attack. It may be a very fresh release that an update bot picked too early.
ERR_PNPM_TRUST_DOWNGRADE means the package has weaker trust evidence than earlier published versions. Do not immediately ignore it. First check the release, publisher, changelog, and whether this exact version is needed now.
ERR_PNPM_NO_MATURE_MATCHING_VERSION in strict mode usually means the requested range has no version that is both semver-compatible and old enough. Your options are to wait, widen the range, pin an older version temporarily, or add a narrow exception.
5. Keep exceptions small
pnpm supports minimumReleaseAgeExclude and trustPolicyExclude. These are valid tools when a package really needs to bypass a rule:
minimumReleaseAge: 1440
minimumReleaseAgeStrict: true
minimumReleaseAgeExclude:
- "@your-org/*"
- "vite@8.0.1"
trustPolicy: no-downgrade
trustPolicyExclude:
- "internal-tool@2.4.0"
The rule for exceptions is package, reason, owner, review date. If you exclude a whole scope, write down why. If you exclude an exact version, schedule removal after the next stable release.
Do not make exceptions the first reflex. If a new package has not passed age policy, the best answer is often to wait a day. If trustPolicy fires, ten minutes of checking is better than teaching CI to bypass protection.
6. Align Renovate, Dependabot, and caches
Automated dependency PRs now need to pass the same policy. For Renovate or Dependabot, that means:
- do not merge a dependency update immediately after publication if
minimumReleaseAgeis supposed to wait; - run
pnpm install —frozen-lockfileon the PR; - avoid caches that make the policy smoke test verify nothing meaningful;
- pin pnpm and Node versions in release branches.
Also check whether your update bot creates the lockfile with an older pnpm. The cleanest setup is one package manager version across local development, bots, and CI.
Anti-Patterns
- adding
minimumReleaseAgeto config without testing the existing lockfile; - disabling strict mode only because the first CI run turned red;
- adding
@scope/*to exclusions without an owner and a deadline; - treating
—frozen-lockfileas a full security guarantee; - caching the pnpm store so aggressively that the policy smoke test skips the real install-flow;
- ignoring
ERR_PNPM_TRUST_DOWNGRADEbecause the package is popular; - upgrading pnpm in CI without a small manual rollout.
Conclusion / Action Plan
pnpm 11.1.3 makes dependency policy more honest: it checks not only fresh resolution, but also an existing pnpm-lock.yaml. That may break CI, but it is how the team learns that an old lockfile does not match current rules.
Practical 30-minute plan:
- pin the pnpm version in
packageManager; - check
minimumReleaseAge,minimumReleaseAgeStrict, andtrustPolicy; - run a clean
pnpm install —frozen-lockfile; - handle ERR codes directly instead of disabling policy globally;
- add only narrow exceptions;
- align Renovate, Dependabot, CI cache, and release branches.
If you already use minimumReleaseAge or trustPolicy: no-downgrade, do not wait for the first random CI failure. Run the smoke test yourself and turn a red install into a controlled rollout.
Official sources:
Quick checklist
- Check which pnpm version runs locally and in CI.
- Open pnpm-workspace.yaml and find minimumReleaseAge, minimumReleaseAgeStrict, trustPolicy, and exclusions.
- Run a clean pnpm install --frozen-lockfile without depending on an old CI cache.
- Test a lockfile created by an older pnpm version or a different environment.
- Add exclusions only narrowly and with an owner.
- Document rollback for common pnpm ERR codes.
Prompt Pack: roll out pnpm lockfile policy in CI
Help safely roll out pnpm supply-chain policy in our Node.js/TypeScript project. Input data: - current pnpm version in local development and CI; - pnpm-workspace.yaml snippet; - whether minimumReleaseAge, minimumReleaseAgeStrict, minimumReleaseAgeExclude, trustPolicy, or trustPolicyExclude is configured; - how CI install runs; - whether --frozen-lockfile is used; - whether pnpm-lock.yaml, the store, or node_modules are cached; - which packages are updated automatically by Renovate, Dependabot, or internal scripts. Return: 1. short diagnosis: does the policy really protect the install-flow or only look configured; 2. risk list for the current pnpm-lock.yaml; 3. recommended pnpm-workspace.yaml for strict or loose behavior; 4. which packages may go into minimumReleaseAgeExclude or trustPolicyExclude, and which should not; 5. one CI smoke test with pnpm install --frozen-lockfile; 6. rollback plan for ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION, ERR_PNPM_TRUST_DOWNGRADE, or ERR_PNPM_NO_MATURE_MATCHING_VERSION. Response format: diagnosis, config diff, CI command, exception list with rationale, 30-minute rollout plan.