[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
In a pnpm workspace with sharedWorkspaceLockfile: false, each member has its own pnpm-lock.yaml. Since #598, a hosted run from such a member is allowed: governing_root.rs treats "a member with its own lock" as its own lock root. The member's lock is then pinned correctly. On pnpm 11 and 12, though, the trust config lands in the wrong file. Hosted mode creates a new pnpm-workspace.yaml inside the member (packages: ['.'] + trustLockfile: true) instead of adding the key to the workspace root's pnpm-workspace.yaml.
pnpm reads settings only from the workspace root. On the next install from the root (the normal way to install this workspace), pnpm 11 / 12 print:
The settings in packages/a/pnpm-workspace.yaml do not apply, because packages/a is a project of this workspace. pnpm reads settings only from the pnpm-workspace.yaml at the workspace root.
They then fail with ERR_PNPM_TARBALL_URL_MISMATCH. The scan itself exits 0 with status: success. Its redirect_pnpm_trust_lockfile warning says the key "was written to a new pnpm-workspace.yaml — commit it alongside the lock; installs need no extra flags", which isn't true for this layout.
Impact
Following the CLI's instructions breaks every install of the workspace on pnpm 11/12: plain pnpm install and --frozen-lockfile alike exit 1. It fails loudly, not silently. Still, the run reported success and told the user to commit the files. The obvious way out is pnpm's own advice to rebuild the lockfile, which the warning itself says discards the hosted patch. The nested packages: ['.'] file also makes packages/a a separate workspace whenever pnpm runs from inside that directory.
Repro (Linux, Node 22)
A local mock of the patch API serves a hosted left-pad@1.3.0 tarball (batch / by-package / view / patches/package grant routes, as in crates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs), with SOCKET_PATCH_SERVER_URL pointed at it.
mkdir -p ws/packages/a && cd ws
echo '{"name":"root","private":true}' > package.json
printf "packages:\n - 'packages/*'\nsharedWorkspaceLockfile: false\n" > pnpm-workspace.yaml
echo '{"name":"a","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > packages/a/package.json
pnpm install # pnpm 12.8.1: writes packages/a/pnpm-lock.yaml (plus an empty root lock)
cd packages/a
socket-patch scan --mode hosted --json --yes --api-url $MOCK --org test-org --api-token fake
# exit 0, status success, redirected 1, rewrittenFiles [pnpm-lock.yaml, pnpm-workspace.yaml]
cat pnpm-workspace.yaml # NEW file in the member: packages: ['.'] / trustLockfile: true
cd ../.. && rm -rf node_modules packages/a/node_modules
pnpm install --frozen-lockfile --store-dir "$(mktemp -d)"
# WARN The settings in packages/a/pnpm-workspace.yaml do not apply ...
# ERR_PNPM_TARBALL_URL_MISMATCH left-pad@1.3.0 has a tarball URL (http://…/patch/npm/left-pad/…) that does not match the registry's published metadata
# exit 1 (plain `pnpm install` also exits 1)
echo 'trustLockfile: true' >> pnpm-workspace.yaml # the key in the ROOT workspace file
pnpm install --frozen-lockfile --store-dir "$(mktemp -d)" # exit 0, left-pad patched
Expected vs actual
- Expected: CLI_CONTRACT.md (scan arguments, pnpm trust-config note) says hosted mode "ensures
pnpm-workspace.yaml carries trustLockfile: true" so that pnpm >= 11 accepts the hosted URLs and "installs need no extra flags". For a workspace member, the file pnpm reads is the workspace root's pnpm-workspace.yaml. Hosted mode should add the key there, or refuse with a clear code, as it already does with redirect_pnpm_lockfile_elsewhere for a member without its own lock.
- Actual: a nested member
pnpm-workspace.yaml that pnpm ignores. The scan reports success, and every root install fails on pnpm 11/12.
OS × version (Linux, main 9c43dfc; each cell run twice)
| pnpm |
layout |
scan |
root install --frozen-lockfile |
| 9.15.9 |
shared-workspace-lockfile=false in .npmrc |
success, nested file written |
pass (pnpm ≤10 ignores the key) |
| 10.34.5 |
.npmrc |
success, nested file written |
pass |
| 11.28.3 |
sharedWorkspaceLockfile: false in pnpm-workspace.yaml |
success, nested file written |
fail: ERR_PNPM_TARBALL_URL_MISMATCH, exit 1 |
| 12.8.1 |
pnpm-workspace.yaml |
success, nested file written |
fail: ERR_PNPM_TARBALL_URL_MISMATCH, exit 1 |
macOS and Windows weren't probed. The logic is path-only and not OS-specific.
First bad release
Not a regression: release 4.0.0 writes the same nested file, and the root frozen install fails the same way on pnpm 12.8.1.
Suspect code
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
In a pnpm workspace with
sharedWorkspaceLockfile: false, each member has its ownpnpm-lock.yaml. Since #598, a hosted run from such a member is allowed:governing_root.rstreats "a member with its own lock" as its own lock root. The member's lock is then pinned correctly. On pnpm 11 and 12, though, the trust config lands in the wrong file. Hosted mode creates a newpnpm-workspace.yamlinside the member (packages: ['.']+trustLockfile: true) instead of adding the key to the workspace root'spnpm-workspace.yaml.pnpm reads settings only from the workspace root. On the next install from the root (the normal way to install this workspace), pnpm 11 / 12 print:
They then fail with
ERR_PNPM_TARBALL_URL_MISMATCH. The scan itself exits 0 withstatus: success. Itsredirect_pnpm_trust_lockfilewarning says the key "was written to a new pnpm-workspace.yaml — commit it alongside the lock; installs need no extra flags", which isn't true for this layout.Impact
Following the CLI's instructions breaks every install of the workspace on pnpm 11/12: plain
pnpm installand--frozen-lockfilealike exit 1. It fails loudly, not silently. Still, the run reported success and told the user to commit the files. The obvious way out is pnpm's own advice to rebuild the lockfile, which the warning itself says discards the hosted patch. The nestedpackages: ['.']file also makespackages/aa separate workspace whenever pnpm runs from inside that directory.Repro (Linux, Node 22)
A local mock of the patch API serves a hosted
left-pad@1.3.0tarball (batch / by-package / view /patches/packagegrant routes, as incrates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs), withSOCKET_PATCH_SERVER_URLpointed at it.Expected vs actual
pnpm-workspace.yamlcarriestrustLockfile: true" so that pnpm >= 11 accepts the hosted URLs and "installs need no extra flags". For a workspace member, the file pnpm reads is the workspace root'spnpm-workspace.yaml. Hosted mode should add the key there, or refuse with a clear code, as it already does withredirect_pnpm_lockfile_elsewherefor a member without its own lock.pnpm-workspace.yamlthat pnpm ignores. The scan reports success, and every root install fails on pnpm 11/12.OS × version (Linux, main
9c43dfc; each cell run twice)install --frozen-lockfileshared-workspace-lockfile=falsein.npmrc.npmrcsharedWorkspaceLockfile: falseinpnpm-workspace.yamlERR_PNPM_TARBALL_URL_MISMATCH, exit 1pnpm-workspace.yamlERR_PNPM_TARBALL_URL_MISMATCH, exit 1macOS and Windows weren't probed. The logic is path-only and not OS-specific.
First bad release
Not a regression: release 4.0.0 writes the same nested file, and the root frozen install fails the same way on pnpm 12.8.1.
Suspect code
crates/socket-patch-core/src/hosted/engine.rs:876:read_workspacereads only<cwd>/pnpm-workspace.yaml.pnpm_trust(engine.rs:1196, the plan at:1318) then plans aCreatethere, without looking for an ancestor workspace root.crates/socket-patch-core/src/hosted/governing_root.rs:54/:106: the member-with-own-lock layout is deliberately let through (the unit test at:254), but the trust-file location wasn't adjusted for it.sharedWorkspaceLockfile: falseignores the per-package pnpm-lock.yaml files and reports success while redirecting nothing #492 (a run from the root ignores the member locks), Hosted scan/get run from a pnpm workspace member (or withlockfile-dir=..) ignores the parent pnpm-lock.yaml and reports success while pinning nothing #590 (fixed: a member without its own lock now refuses), and Hosted and vendored modes create apackages: ['.']pnpm-workspace.yaml that turns a single-package project into a workspace, sopnpm add <pkg>fails with ERR_PNPM_ADDING_TO_ROOT on pnpm 9.0–10.4 #734 (apackages: ['.']scaffold in a single-package project).