GeezerVison is showing github.com — Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in its `packages:` globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) · Issue #1006 · SocketDev/socket-patch
Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in its packages: globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006Description[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
Since #888 (fix for #880 / #881), hosted and vendored modes refuse any pnpm project with its own v9 pnpm-lock.yaml and no pnpm-workspace.yaml of its own whenever any ancestor directory has a pnpm-workspace.yaml. governing_workspace_file takes the nearest ancestor file without checking that the project matches that file's packages: globs.
pnpm 11 and 12 don't treat such a directory as a workspace project. Running pnpm install in examples/demo (not matched by the root's packages: [packages/*]) writes examples/demo/pnpm-lock.yaml and reads only a pnpm-workspace.yaml in examples/demo, never the root one. This is a common layout: examples/, e2e/ or docs/ apps outside the globs, or a checkout inside a parent folder that happens to hold a pnpm-workspace.yaml.
So on main:
- hosted exits 1 with
redirect_pnpm_settings_elsewhere. Its remedy ("add trustLockfile: true to /pnpm-workspace.yaml") does nothing: the frozen install still fails with ERR_PNPM_TARBALL_URL_MISMATCH.
- vendored fails each package with
vendor_pnpm_settings_elsewhere and tells the user to use --mode hosted, which also refuses. Neither mode can patch the project.
- Release 4.0.0 patches the same project in both modes. The nested
pnpm-workspace.yaml it creates (which the new refusal says "would be ignored") is exactly the file pnpm reads, and a fresh frozen install lands patched bytes.
Impact
Every pnpm 11/12 project nested below an unrelated workspace file stops being patchable in hosted and vendored modes, and both error messages point at remedies that don't work.
Repro (pnpm 12.10.1, Node 22, mock patch API as in the pnpm compatibility e2e)
mkdir -p ws/packages/a ws/examples/demo && cd ws
printf 'packages:\n - packages/*\n' > pnpm-workspace.yaml
echo '{"name":"root","private":true}' > package.json
echo '{"name":"a","version":"1.0.0"}' > packages/a/package.json
echo '{"name":"demo","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0","ms":"2.1.3"}}' > examples/demo/package.json
cd examples/demo && pnpm install # pnpm 11/12: lock written to examples/demo/pnpm-lock.yaml
socket-patch scan --mode hosted --json --yes # exit 1, redirect_pnpm_settings_elsewhere
socket-patch scan --mode vendored --json --yes # exit 1, vendor_pnpm_settings_elsewhere x2
# Proof that the root file doesn't govern demo (pins written with --no-trust-lockfile-config,
# then a fresh frozen install of a copy, empty store):
# C: no trust anywhere -> ERR_PNPM_TARBALL_URL_MISMATCH
# A: `trustLockfile: true` in ws/pnpm-workspace.yaml -> ERR_PNPM_TARBALL_URL_MISMATCH (the advised fix)
# B: `trustLockfile: true` in examples/demo/pnpm-workspace.yaml -> exit 0, left-pad patched
Expected vs actual
CLI_CONTRACT.md scopes both codes to "a pnpm workspace member with its own … pnpm-lock.yaml (sharedWorkspaceLockfile: false)". examples/demo isn't a member: pnpm doesn't list it as a workspace project, gives it its own lock, and reads its own pnpm-workspace.yaml. Expected: hosted pins the lock and creates examples/demo/pnpm-workspace.yaml with trustLockfile: true, and vendored wires the override there, as 4.0.0 does. Actual: both modes refuse, and nothing is written.
OS × version
| OS |
pnpm |
layout (lock location) |
hosted on main |
vendored on main |
4.0.0 |
| Linux |
12.10.1 |
own lock in examples/demo |
refused (reproduced twice), advised fix fails, nested file works |
refused |
hosted + vendored pass, fresh frozen install patched |
| Linux |
11.28.5 |
own lock in examples/demo |
refused, advised fix fails, nested file works |
not run |
not run |
| Linux |
10.34.6 / 9.15.9 |
pnpm installs the root workspace instead (no lock in demo) |
n/a |
n/a |
n/a |
macOS and Windows weren't probed. The logic is path-only and OS-independent.
First bad commit
8e8daf0 (#888). Release 4.0.0 is good.
Suspect code
crates/socket-patch-core/src/utils/pnpm_workspace.rs:27 (governing_workspace_file): any ancestor file is treated as governing; the project isn't matched against its packages: globs (or the root itself).
crates/socket-patch-core/src/hosted/governing_root.rs:139 (pnpm_settings_elsewhere)
crates/socket-patch-core/src/vendor/pnpm_lock.rs:594 (vendored refusal)
No probe runs; Linux only.
Backlog review — 2026-10-08
Priority: P1 → P2. An unrelated ancestor workspace causes a false refusal. Real pnpm usability regression with a narrow nesting trigger. Activitymikolalysenko commented on Oct 7, 2026 CollaboratorAuthor More actions [agent] Claiming this issue as part of the pnpm open-issue sweep in draft PR #1007. Branch: agent/fix-pnpm-open-issues. Claim-ID: 2026-10-07T12:44:29Z-pnpm07 mikolalysenko commented on Oct 7, 2026 CollaboratorAuthor More actions [agent] Triage: priority:p1. pnpm. Already claimed by draft #1007.
Generated by Claude Code mikolalysenko commented on Oct 7, 2026 CollaboratorAuthor More actions [agent] PR #1007 fixes this issue. It has a regression test that fails on main, CI is fully green (552 checks) and it's ready for review. The issue will close when #1007 merges. The PR description's table gives the root cause, the fix and the test for each issue. mikolalysenko commented on Oct 8, 2026 CollaboratorAuthor More actions [agent] New variant from the pnpm bug-hunt routine (ledger #303), main cf8b164, Linux, reproduced twice: a settings-only parent pnpm-workspace.yaml with no packages: key gives the same wrong refusal. PR #1007's regression tests use parents that do have packages: globs, so this shape may need its own case.
Layout: parent/pnpm-workspace.yaml contains only minimumReleaseAge: 0, and parent/child/ is a standalone project depending on [email protected]. Running pnpm install in child/ on pnpm 11.28.5 and 12.10.1 writes child/pnpm-lock.yaml, not a lock at the parent, so pnpm treats the child as its own root.
| pnpm |
scan --mode hosted in child/ |
scan --mode vendored |
Suggested fix (trustLockfile: true in the parent file) → fresh --frozen-lockfile |
trustLockfile: true in child/pnpm-workspace.yaml → fresh --frozen-lockfile |
| 11.28.5 |
exit 1, redirect_pnpm_settings_elsewhere |
not run |
ERR_PNPM_TARBALL_URL_MISMATCH |
pass, patched bytes |
| 12.10.1 |
exit 1, redirect_pnpm_settings_elsewhere |
exit 1, vendor_pnpm_settings_elsewhere |
ERR_PNPM_TARBALL_URL_MISMATCH |
pass, patched bytes |
So, as in the original report, the refusal sends the user to a file pnpm doesn't read for this project. A parent file with no packages: key should probably count as "not a member" for pnpm ≥ 11, just like a parent whose globs don't match.
On pnpm 10.34.6 the same layout installs nothing in child/ (no lock, no node_modules). Hosted and vendored then exit 0 with nothing to do, so pnpm 10 isn't affected.
Generated by Claude Code mikolalysenko commented on Oct 9, 2026 CollaboratorAuthor More actions [agent] pnpm bug-hunt, another variant on main 03b9418: a project excluded by a negated glob.
# pnpm-workspace.yaml at the root
packages:
- 'packages/*'
- '!packages/excluded'
packages/excluded ([email protected]) gets its own pnpm-lock.yaml from pnpm install run inside it, and the root lock has no left-pad. pnpm treats it as outside the workspace.
| pnpm |
scan --mode hosted from packages/excluded |
scan --mode vendored |
| 11.28.5 |
exit 1, redirect_pnpm_settings_elsewhere, nothing written |
not run |
| 12.10.1 |
exit 1, redirect_pnpm_settings_elsewhere, nothing written |
exit 1, vendor_pnpm_settings_elsewhere |
The refusal's remedy is wrong here too (12.10.1, pinned with --no-trust-lockfile-config, then a frozen install with an empty store):
trustLockfile: true appended to the root pnpm-workspace.yaml, as the message suggests: ERR_PNPM_TARBALL_URL_MISMATCH.
trustLockfile: true in a new packages/excluded/pnpm-workspace.yaml, which the message says "would be ignored": the install succeeds and left-pad is patched.
So the membership check needs to honour ! patterns in packages: as well as plain globs.
Generated by Claude Code
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|