#14987·pnpm

`pnpm dedupe` requires two passes after bumping a direct dependency (regression in 11.x)

Author: astegmaierCreated Sep 16, 2026Updated Sep 17, 2026
Labelstype: bugarea: lockfileregressionarea: resolution

Last pnpm version that worked

10.34.5

pnpm version

11.27.0 - the issue does not reproduce in 12.x, though.

Code to reproduce the issue

A complete reproduction repository is available at astegmaier/playground-pnpm-dedupe-instability-bug.

Create an empty directory with this package.json:

json
{
  "name": "pnpm-dedupe-fixed-point-repro",
  "version": "1.0.0",
  "private": true,
  "packageManager": "[email protected]",
  "dependencies": {
    "boxen": "5.1.2",
    "chalk": "4.1.0"
  }
}

Then run:

bash
# Generate a baseline lockfile containing [email protected].
pnpm install

# Bump the direct dependency without updating the lockfile first.
pnpm pkg set 'dependencies.chalk=^4.1.2'

# This should leave the lockfile fully deduplicated.
pnpm dedupe

# This unexpectedly fails.
pnpm dedupe --check

The dependency graph is:

pnpm-dedupe-fixed-point-repro
├── chalk@^4.1.2
└── [email protected]
    └── chalk@^4.1.0

Both [email protected] and [email protected] satisfy boxen's range.

Expected behavior

One invocation of pnpm dedupe should reach a fixed point. Running pnpm dedupe --check immediately afterward should succeed without finding additional lockfile changes.

Actual behavior

The first pnpm dedupe updates the direct dependency to [email protected] but retains [email protected] for boxen. The following check exits with code 1:

[ERR_PNPM_DEDUPE_CHECK_ISSUES] Dedupe --check found changes to the lockfile

Packages
[email protected]
└── chalk 4.1.0 → 4.1.2

- [email protected]

Run pnpm dedupe to apply the changes above.

Running the same commands a second time succeeds:

bash
pnpm dedupe
pnpm dedupe --check

The second dedupe removes [email protected]. The package manifests did not change between the first and second passes.

Additional information

The behavior is deterministic and still reproduces with an empty pnpm metadata cache.

The important starting condition is that the newer version is not yet represented in the lockfile. In pnpm 11, existing lockfile versions receive a much stronger preferred-version weight than a newly resolved direct version. The first pass therefore introduces the newer direct version while retaining the older compatible transitive version. Once both versions are represented in the lockfile, the second pass can converge on the higher compatible version.

pnpm versions Result
8.0.0–8.15.9 ✅ No repro
9.0.0–9.15.9 ✅ No repro
10.0.0–10.34.5 ✅ No repro
11.0.0–11.27.0 ❌ Repro
12.0.0–12.4.2 ✅ No repro

Node.js version

24.16.0

Operating System

macOS