Verify latest release
pnpm version
12.7.0, and a cargo build --bin pnpm of main at 0620e8b
Which area(s) of pnpm are affected? (leave empty if unsure)
Link to the code that reproduces this issue or a replay of the bug
Inline reproduction below, on macOS 26.5 arm64.
Reproduction steps
mkdir repro && cd repro
cat > .pnpmfile.cjs <<'JS'
module.exports = {
hooks: {
readPackage (pkg) {
if (pkg.name === 'is-positive') {
pkg.dependencies = { ...pkg.dependencies, ms: undefined }
}
return pkg
},
},
}
JS
echo '{"name":"repro","private":true,"dependencies":{"is-positive":"3.1.0"}}' > package.json
pnpm install
ls node_modules/ms
ms: undefined may also be null, a number, or any other non-string.
Describe the Bug
pnpm 12 drops the dependency and reports success:
Packages: +1
+
Progress: resolved 1, reused 0, downloaded 1, added 1, done
dependencies:
+ is-positive 3.1.0
Done in 222ms using pnpm v12.7.0
node_modules/ms does not exist, and nothing is printed about it. The same hook leaves pnpm 11 with
[ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULT] readPackage hook returned an invalid range for 'ms' in the 'dependencies' of debug@4.3.4. Expected a string, got undefined. To remove the dependency, delete the property. Hook imported via /path/to/.pnpmfile.cjs
Expected Behavior
The install fails, naming the dependency, the field, the package and the pnpmfile, as pnpm 11 does.
Where it comes from
readPackage runs in the Node worker, which returns the manifest as JSON (pnpm/crates/hooks/src/worker.cjs). worker.cjs checks that each of dependencies, devDependencies, optionalDependencies and peerDependencies is an object, but not that its values are strings, and JSON.stringify drops a key whose value is undefined. The entry is therefore gone before the resolver sees the manifest, and the install proceeds without the dependency.
pnpm 11 rejects the manifest since #15326, which closed #5517 for the TypeScript CLI only and noted that "the Rust CLI … non-string ranges are dropped". This issue is the remaining half of that report: pnpm/tasks#7 lists it as "the dependency is dropped with no warning and no error" on 12.5.1.
A value that is a non-string is a malformed manifest, so failing the install is what both stacks now do. ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULT is the one thing still missing here: every hook failure carries ERR_PNPM_PNPMFILE_FAIL in pacquet, as the comment on ResolveDependencyTreeError::PnpmfileHook (pnpm/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs) already records.
Which Node.js version are you using?
22.23.1
Which operating systems have you used?
Written by an agent (OpenCode, space-bunny-free).
Verify latest release
pnpm version
12.7.0, and a
cargo build --bin pnpmofmainat 0620e8bWhich area(s) of pnpm are affected? (leave empty if unsure)
Link to the code that reproduces this issue or a replay of the bug
Inline reproduction below, on macOS 26.5 arm64.
Reproduction steps
ms: undefinedmay also benull, a number, or any other non-string.Describe the Bug
pnpm 12 drops the dependency and reports success:
node_modules/msdoes not exist, and nothing is printed about it. The same hook leaves pnpm 11 withExpected Behavior
The install fails, naming the dependency, the field, the package and the pnpmfile, as pnpm 11 does.
Where it comes from
readPackageruns in the Node worker, which returns the manifest as JSON (pnpm/crates/hooks/src/worker.cjs).worker.cjschecks that each ofdependencies,devDependencies,optionalDependenciesandpeerDependenciesis an object, but not that its values are strings, andJSON.stringifydrops a key whose value isundefined. The entry is therefore gone before the resolver sees the manifest, and the install proceeds without the dependency.pnpm 11 rejects the manifest since #15326, which closed #5517 for the TypeScript CLI only and noted that "the Rust CLI … non-string ranges are dropped". This issue is the remaining half of that report: pnpm/tasks#7 lists it as "the dependency is dropped with no warning and no error" on 12.5.1.
A value that is a non-string is a malformed manifest, so failing the install is what both stacks now do.
ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULTis the one thing still missing here: every hook failure carriesERR_PNPM_PNPMFILE_FAILin pacquet, as the comment onResolveDependencyTreeError::PnpmfileHook(pnpm/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs) already records.Which Node.js version are you using?
22.23.1
Which operating systems have you used?
Written by an agent (OpenCode, space-bunny-free).