[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
For any project with a lockfileVersion 9.0 pnpm-lock.yaml and no pnpm-workspace.yaml, scan --mode hosted creates the scaffold
packages:
- '.'
trustLockfile: true
and scan --mode vendored creates the same packages: ['.'] scaffold with an overrides: block. On pnpm 9.0.0 through 10.4.1, that file makes pnpm treat the plain single-package project as a workspace whose only member is the root. The most common day-to-day command, pnpm add <pkg>, then fails:
ERR_PNPM_ADDING_TO_ROOT Running this command will add the dependency to the workspace root, which might not be what you want - if you really meant it, make it explicit by running this command again with the -w flag (or --workspace-root). ...
Nothing is added to package.json or the lock. Before the scan, the same pnpm add works.
The packages: key can't just be dropped. pnpm 9 refuses a workspace file without it (ERROR packages field missing or empty, checked below), and the code comment at guidance.rs says the scaffold exists for that reason. On these versions the hosted half is also unnecessary: the docs say pnpm <= 10 doesn't need trustLockfile ("pnpm >=11 needs this for hosted URLs … pnpm <=10 does not need the setting", docs/ecosystems.md). So hosted mode changes the project's pnpm semantics for a setting those pnpm versions don't use.
Impact
- Every developer and CI job on pnpm 9.x (and 10.0–10.4) that later runs
pnpm add <pkg> in a project socket-patch touched gets a hard error. The error message talks about workspaces, not socket-patch, so the link to the scan isn't obvious.
- This affects hosted mode, which is the v5 default for a bare
scan, and vendored mode.
- The workaround is
pnpm add -w <pkg> or ignore-workspace-root-check=true. With -w the hosted pin survives, which I checked on 9.15.9.
Repro (Linux, Node 22)
mkdir app && cd app
printf '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}\n' > package.json
npx pnpm@9.15.9 install
npx pnpm@9.15.9 add is-number@7.0.0 # control: works (then revert, or use a fresh dir)
# fresh dir, same package.json + install, then:
socket-patch scan --mode hosted --yes # (or --mode vendored)
cat pnpm-workspace.yaml # packages: ['.'] + trustLockfile: true
npx pnpm@9.15.9 add is-number@7.0.0 # ERR_PNPM_ADDING_TO_ROOT, exit 1, nothing added
(I used a local mock of the patch API serving a real patched left-pad@1.3.0 tarball. Any granted pnpm 9.0 lock pin reproduces it.)
Control showing why packages: is needed on pnpm 9:
printf 'trustLockfile: true\n' > pnpm-workspace.yaml
npx pnpm@9.15.9 add is-number@7.0.0 # ERROR packages field missing or empty
npx pnpm@9.15.9 install --frozen-lockfile # ERROR packages field missing or empty
Expected vs actual
- Expected: CLI_CONTRACT says the hosted write "preserves user bytes" and that installs "need no extra flags". It describes the scaffold only as a vehicle for
trustLockfile, which pnpm >= 11 requires. Ensuring trust (or vendored overrides) shouldn't change how the user's own pnpm commands behave, and on pnpm <= 10 hosted mode doesn't need the file at all.
- Actual: after a successful scan,
pnpm add <pkg> exits 1 with ERR_PNPM_ADDING_TO_ROOT on pnpm 9.0.0 – 10.4.1.
Matrix (Linux, socket-patch main 045d7ec; pnpm add is-number@7.0.0 after the scan)
| pnpm |
hosted |
vendored |
control (no scan) |
| 9.0.0 |
fail ADDING_TO_ROOT |
untested |
pass |
| 9.7.1 |
fail |
untested |
pass |
| 9.15.9 |
fail (3×) |
fail |
pass |
| 10.0.0 |
fail (2×) |
fail |
pass |
| 10.1.0 / 10.2.1 / 10.3.0 / 10.4.1 |
fail |
untested |
pass |
| 10.5.0 / 10.5.2 / 10.12.1 / 10.34.5 |
pass |
pass (10.5.0) |
pass |
| 11.0.0 / 11.28.3 / 12.8.1 |
pass (see note) |
untested |
pass |
| 7.33.7 / 8.15.9 |
n/a (legacy locks get no scaffold) |
n/a |
pass |
pnpm 10.5.0 is the first pnpm release that no longer refuses in a root-only workspace.
Note, not part of this bug: on pnpm 11.0.0 / 11.28.3, pnpm add <other> succeeds but re-resolves the hosted pin back to upstream. pnpm 9, 10 and 12 keep it. That's the same pnpm 11 re-resolution recorded in #713.
Not a regression: release 4.0.0 writes the same scaffold and fails the same way on pnpm 9.15.9. 3.3.0 has no hosted mode.
Suspect code
crates/socket-patch-core/src/hosted/guidance.rs:252: TrustPlan::Create("packages:\n - '.'\ntrustLockfile: true\n") runs for every 9.0 root lock, whatever pnpm version the project uses.
crates/socket-patch-core/src/vendor/pnpm_lock.rs:95: WS_SCAFFOLD_PACKAGES, the same root-only scaffold on the vendored side.
Possible directions (for maintainers): skip creating the hosted scaffold when the project pins pnpm <= 10 (packageManager, engines, devEngines), since pnpm <= 10 doesn't need the key; or also write ignore-workspace-root-check=true (.npmrc) / ignoreWorkspaceRootCheck: true when socket-patch creates the scaffold; or at least document the -w requirement in the redirect_pnpm_trust_lockfile detail and in pnpm-compatibility.md.
No probe runs: this is Linux-only evidence. The behaviour comes from pnpm's own workspace detection, so I don't expect it to depend on the OS.
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
For any project with a lockfileVersion 9.0
pnpm-lock.yamland nopnpm-workspace.yaml,scan --mode hostedcreates the scaffoldand
scan --mode vendoredcreates the samepackages: ['.']scaffold with anoverrides:block. On pnpm 9.0.0 through 10.4.1, that file makes pnpm treat the plain single-package project as a workspace whose only member is the root. The most common day-to-day command,pnpm add <pkg>, then fails:Nothing is added to
package.jsonor the lock. Before the scan, the samepnpm addworks.The
packages:key can't just be dropped. pnpm 9 refuses a workspace file without it (ERROR packages field missing or empty, checked below), and the code comment atguidance.rssays the scaffold exists for that reason. On these versions the hosted half is also unnecessary: the docs say pnpm <= 10 doesn't needtrustLockfile("pnpm >=11 needs this for hosted URLs … pnpm <=10 does not need the setting", docs/ecosystems.md). So hosted mode changes the project's pnpm semantics for a setting those pnpm versions don't use.Impact
pnpm add <pkg>in a project socket-patch touched gets a hard error. The error message talks about workspaces, not socket-patch, so the link to the scan isn't obvious.scan, and vendored mode.pnpm add -w <pkg>orignore-workspace-root-check=true. With-wthe hosted pin survives, which I checked on 9.15.9.Repro (Linux, Node 22)
(I used a local mock of the patch API serving a real patched
left-pad@1.3.0tarball. Any granted pnpm 9.0 lock pin reproduces it.)Control showing why
packages:is needed on pnpm 9:Expected vs actual
trustLockfile, which pnpm >= 11 requires. Ensuring trust (or vendored overrides) shouldn't change how the user's own pnpm commands behave, and on pnpm <= 10 hosted mode doesn't need the file at all.pnpm add <pkg>exits 1 withERR_PNPM_ADDING_TO_ROOTon pnpm 9.0.0 – 10.4.1.Matrix (Linux, socket-patch main
045d7ec;pnpm add is-number@7.0.0after the scan)pnpm 10.5.0 is the first pnpm release that no longer refuses in a root-only workspace.
Note, not part of this bug: on pnpm 11.0.0 / 11.28.3,
pnpm add <other>succeeds but re-resolves the hosted pin back to upstream. pnpm 9, 10 and 12 keep it. That's the same pnpm 11 re-resolution recorded in #713.Not a regression: release 4.0.0 writes the same scaffold and fails the same way on pnpm 9.15.9. 3.3.0 has no hosted mode.
Suspect code
crates/socket-patch-core/src/hosted/guidance.rs:252:TrustPlan::Create("packages:\n - '.'\ntrustLockfile: true\n")runs for every 9.0 root lock, whatever pnpm version the project uses.crates/socket-patch-core/src/vendor/pnpm_lock.rs:95:WS_SCAFFOLD_PACKAGES, the same root-only scaffold on the vendored side.Possible directions (for maintainers): skip creating the hosted scaffold when the project pins pnpm <= 10 (
packageManager,engines,devEngines), since pnpm <= 10 doesn't need the key; or also writeignore-workspace-root-check=true(.npmrc) /ignoreWorkspaceRootCheck: truewhen socket-patch creates the scaffold; or at least document the-wrequirement in theredirect_pnpm_trust_lockfiledetail and in pnpm-compatibility.md.No probe runs: this is Linux-only evidence. The behaviour comes from pnpm's own workspace detection, so I don't expect it to depend on the OS.