Repository navigation
Vendored pnpm with two or more packages: vendor --revert and rollback leave an empty pnpm.overrides in package.json and (lockfile 9.0) a scaffolded pnpm-workspace.yaml behind #636
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:pnpmpnpmpnpm
on Oct 3, 2026 - changed the title
[-]Vendored pnpm with two or more packages: vendor --revert and rollback leave an empty `pnpm.overrides` in package.json and (pnpm 11+) a scaffolded pnpm-workspace.yaml behind[/-][+]Vendored pnpm with two or more packages: vendor --revert and rollback leave an empty `pnpm.overrides` in package.json and (lockfile 9.0) a scaffolded pnpm-workspace.yaml behind[/+]on Oct 3, 2026 mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] Triaged:
priority:p1(pnpm). Not a duplicate, and no open or merged PR addresses it. Confirmed on main045d7ec: the vendored pnpm backend recordscreated_pnpm_table/created_overrides_table/created_workspace_fileonly on the entry that first created them (vendor/pnpm_lock.rs:402-404). The revert at:906and:969only removes a table or the workspace file when the entry it is reverting carries the flag, so if a flag-less entry is the one that empties the table, the residue stays. A fix should make "who created it" a property of the shared artifact, not of one ledger entry: either carry the flag forward to the surviving entries, or check "empty and created by vendoring" when the last entry is reverted.
Generated by Claude Code
mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue together with #670. The shared root cause: vendored wiring records "vendor created this shared table/file" on only the first ledger entry, so a revert removes the scaffold only when that entry happens to be reverted last. Branch: agent/fix-vendor-created-scaffold-ownership. Claim-ID: 2026-10-03T09:20:28Z-18043c
Generated by Claude Code
mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions- added 5 commits that reference this issue
on Oct 3, 2026 mikolalysenko commented
on Oct 4, 2026 CollaboratorAuthorMore actions[agent] New path for the same residue, from the pnpm bug-hunt routine (ledger #303), main
045d7ec, Linux. This is worth checking that PR #672 covers.A vendored → hosted takeover with two packages (
left-pad@1.3.0+is-number@7.0.0, thenscan --mode vendored, thenscan --mode hosted) leaves the same"pnpm": {"overrides": {}}inpackage.jsonand the vendoredpnpm-workspace.yamlscaffold. Hosted mode then appendstrustLockfile: trueto that leftover file:packages: - '.' overrides: trustLockfile: trueBecause the file is no longer exactly hosted mode's own scaffold, a later full
rollbackcan't delete it either. The lock comes back byte-exact, but the 4-line workspace file and the emptypnpm.overridesstay for good, and rollback only warnspnpm_trust_lockfile_left. A frozen install after the takeover is patched, so it's still residue only.pnpm 2 packages: vendored → hosted → rollback 1 package (control) 8.15.9 (6.0) package.jsonresidue— 9.15.9 / 10.34.5 package.json+ 4-line workspace residue— 12.8.1 package.json+ 4-line workspace residue (reproduced 2×)clean (scaffold deleted, lock byte-exact)
Generated by Claude Code
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
On a pnpm project with no
pnpm.overridesand nopnpm-workspace.yaml, vendoring two or more packages and then runningvendor --revert(orrollback) restorespnpm-lock.yamlbyte-exactly. But it leaves"pnpm": { "overrides": {} }inpackage.json. On a lockfile 9.0 project (pnpm 9–12) it also leaves apnpm-workspace.yamlthat vendoring created (packages: ['.']plus an emptyoverrides:key). With exactly one vendored package the revert is byte-exact. Release 4.0.0 is byte-exact with two packages too, so this is a regression.Impact
After a full revert the checkout isn't back to its pre-vendor state. Two tracked files are dirty (one of them new) and need a manual cleanup commit. The leftover
pnpm-workspace.yamlalso turns a single-package project into a workspace root as far as pnpm is concerned. Frozen installs still pass and the lock is untouched, so this isn't a supply-chain break. It's a "revert leaves residue" bug: the contract forvendor --revertis to "restore recorded original lockfile fragments", and the backend trackscreatedPnpmTable/createdOverridesTable/createdWorkspaceFileprecisely so that it can delete what it created.Repro (main
045d7ec, Linux, Node 22)The result after the revert (pnpm 12.8.1;
pnpm-lock.yamlis byte-identical to the original):socket-patch rollbackgives the same result. On pnpm 7/8 (legacy 5.4 / 6.0 locks) only thepackage.jsonresidue appears, because the legacy dialect doesn't mirror overrides into a workspace file.Why
The ledger records the "created" flags only on the entry that was vendored first (
.socket/vendor/state.json):The revert then processes entries in that same order (
is-number, thenleft-pad). When the creator entry is reverted,left-pad's key still keeps the table and the workspace file non-empty, so nothing is removed. Whenleft-padis reverted last and empties them, it has no "created" flags, so it keeps them (crates/socket-patch-core/src/vendor/pnpm_lock.rs:901-930forpackage.json, and:961-985→revert_workspaceforpnpm-workspace.yaml). Removing the entries one at a time withremove <purl>in the opposite order (left-padfirst, thenis-number) cleans up correctly, which confirms that it depends on order.Expected vs actual
pnpm.overridestable,pnpmtable andpnpm-workspace.yamlthat vendoring created are removed, sopackage.jsonand the workspace come back byte-exact. That's what the pnpm backend's created-table tracking is for, and the single-package revert already does it.rollback)Every 2-package cell reproduced at least twice on main, and a
--frozen-lockfileinstall after the revert passes in every cell.Release 4.0.0 (npm
@socketsecurity/socket-patch@4.0.0), same fixture with 2 packages: byte-exact on 8.15.9 and 12.8.1, with the same ledger flags and the same revert event order.First bad commit
Bisected on pnpm 12.8.1 with the two-package fixture:
09956d90"Cleanup: no .socket residue, locks that never outlive a command, manifest-free vendored mode (#247)" is the first bad commit. Its parent9489b185(#246) is good, and every commit tested between it and main is bad. The recent pnpm vendoring refactor (#583,fc356c0) didn't introduce it:b8bf049, just before it, is already bad.