Verify latest release
pnpm version
11.1.2
Which area(s) of pnpm are affected?
Lockfile, Package manager compatibility
Link to the code that reproduces this issue or a replay of the bug
(steps below are self-contained)
Reproduction steps
Part 1: packageManagerDependencies not written without onFail
mkdir /tmp/test-devengines && cd /tmp/test-devengines
cat > package.json << 'EOF'
{
"private": true,
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": ">=11.0.0"
}
},
"dependencies": {
"is-odd": "^3.0.1"
}
}
EOF
cat > pnpm-workspace.yaml << 'EOF'
---
EOF
pnpm install
head -20 pnpm-lock.yaml
# Expected: packageManagerDependencies with resolved version
# Actual: no packageManagerDependencies at all
Part 2: Adding onFail: "download" triggers the write
cat > package.json << 'EOF'
{
"private": true,
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": ">=11.0.0",
"onFail": "download"
}
},
"dependencies": {
"is-odd": "^3.0.1"
}
}
EOF
rm -rf node_modules
pnpm install
head -20 pnpm-lock.yaml
# Now packageManagerDependencies appears with @pnpm/exe and platform-specific entries
Part 3: Removing onFail does NOT clean up
cat > package.json << 'EOF'
{
"private": true,
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": ">=11.0.0"
}
},
"dependencies": {
"is-odd": "^3.0.1"
}
}
EOF
rm -rf node_modules
pnpm install
head -20 pnpm-lock.yaml
# Expected: packageManagerDependencies removed (onFail no longer set)
# Actual: packageManagerDependencies and all @pnpm/exe entries still present
Describe the Bug
Two related issues with devEngines.packageManager and lockfile behavior:
-
Without onFail: pnpm install does not write packageManagerDependencies to the lockfile at all, even though the docs say "The resolved version is stored in pnpm-lock.yaml" unconditionally. The user has to discover through trial-and-error that onFail: "download" is the trigger.
-
Removing onFail after it was set: The packageManagerDependencies entries (including ~7 @pnpm/* platform-specific binary packages) remain in the lockfile indefinitely. There's no way to clean them up short of deleting the lockfile and regenerating.
This creates a confusing experience: the feature appears broken without onFail, then once you add onFail to debug it, you get 200+ extra lines in your lockfile that you can't undo.
Expected Behavior
-
devEngines.packageManager should write packageManagerDependencies to the lockfile regardless of whether onFail is set. The onFail field controls runtime behavior (what to do on mismatch), not whether the resolution is recorded.
-
If onFail: "download" is removed, pnpm install should prune the @pnpm/exe entries from the lockfile since the download mechanism is no longer active and those entries serve no purpose.
Which Node.js version are you using?
v26.0.0
Which operating systems have you used?
Verify latest release
pnpm version
11.1.2
Which area(s) of pnpm are affected?
Lockfile, Package manager compatibility
Link to the code that reproduces this issue or a replay of the bug
(steps below are self-contained)
Reproduction steps
Part 1:
packageManagerDependenciesnot written withoutonFailPart 2: Adding
onFail: "download"triggers the writePart 3: Removing
onFaildoes NOT clean upDescribe the Bug
Two related issues with
devEngines.packageManagerand lockfile behavior:Without
onFail:pnpm installdoes not writepackageManagerDependenciesto the lockfile at all, even though the docs say "The resolved version is stored inpnpm-lock.yaml" unconditionally. The user has to discover through trial-and-error thatonFail: "download"is the trigger.Removing
onFailafter it was set: ThepackageManagerDependenciesentries (including ~7@pnpm/*platform-specific binary packages) remain in the lockfile indefinitely. There's no way to clean them up short of deleting the lockfile and regenerating.This creates a confusing experience: the feature appears broken without
onFail, then once you addonFailto debug it, you get 200+ extra lines in your lockfile that you can't undo.Expected Behavior
devEngines.packageManagershould writepackageManagerDependenciesto the lockfile regardless of whetheronFailis set. TheonFailfield controls runtime behavior (what to do on mismatch), not whether the resolution is recorded.If
onFail: "download"is removed,pnpm installshould prune the@pnpm/exeentries from the lockfile since the download mechanism is no longer active and those entries serve no purpose.Which Node.js version are you using?
v26.0.0
Which operating systems have you used?