Vendored pnpm 12 with `packageManager` set: the two-document pnpm-lock.yaml makes vendor refuse, and `vendor --revert`, rollback and the hosted takeover half-revert the project and break frozen installs
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 65/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- javascript, rust
- Bereich
- build-system, cli, tooling
Rechercherichtung
Run the supplied pnpm 12.8.1 reproduction and inspect crates/socket-patch-core/src/formats/pnpm/lines.rs:14, formats/pnpm/mod.rs:290, and vendor/pnpm_lock.rs:509 plus line 1285. Verify that vendor, vendor --revert, rollback, and default hosted takeover address the project lock document, preserve the ledger and wiring, and leave pnpm install --frozen-lockfile working.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
When package.json has a packageManager: "[email protected]" field, pnpm 12 writes pnpm-lock.yaml as two YAML documents. The first is an "env" document with its own importers: (configDependencies, packageManagerDependencies), packages: (the pnpm / @pnpm/exe.* entries) and snapshots:. The second is the project lock. pnpm 11.28.3 and 10.34.5 don't do this with the same package.json.
The vendored line-block planner finds sections with section_bounds, which returns the first column-0 packages: / importers: / snapshots: header. So on this lock it reads and edits the env document, except for overrides:, which exists only in the second document. As a result:
scan --mode vendored/vendorrefuses wrongly. It reportsvendor_lock_entry_not_found("pnpm-lock.yaml has no packages entry for [email protected] — make sure the package is installed and locked"), but the package is installed and locked. This fails closed (exit 1), but the refusal shouldn't fire.vendor --reverton a project vendored before the lock became two-doc: exit 0,status: success. It removespnpm.overridesfrom package.json, deletes the scaffolded pnpm-workspace.yaml and removes the lock'soverrides:block. It leaves all 5file:.socket/vendor/...references in the importers, packages and snapshots of document 2. Every event isskipped/vendor_lock_entry_drifted("packages entry ... no longer exists"), which is false. The nextpnpm install --frozen-lockfilefails withERR_PNPM_OUTDATED_LOCKFILE.rollbackdoes the same edits. It then reportsvendoredKept: [{reason: "lockfile wiring drifted; vendored state left untouched"}]and exits 1. The state was not left untouched: package.json, pnpm-workspace.yaml and the lock were all modified, and frozen installs break.- Plain
scan(v5 default hosted mode) does a vendored→hosted takeover. It warnsredirect_takeover_reverted_vendored, deletes the vendor ledger (.socket/vendor/state.json), package.json overrides, the workspace file and the lockoverrides:block, then warnsredirect_pnpm_entry_vendoredwithredirected: 0. It exits 0 withstatus: success. The project is left with no ledger, no hosted pin and a lock that--frozen-lockfilerejects (ERR_PNPM_OUTDATED_LOCKFILE). Because the ledger is gone, a laterrollbackcan only say "lockfiles still reference .socket/vendor/ artifacts but the vendor ledger is missing".
Hosted mode itself is fine on the two-doc lock. scan --mode hosted pins the entry in document 2, a fresh dead-registry frozen install lands the patched bytes, vex attests not_affected, and rollback restores the lock byte for byte.
Impact
packageManager is the standard way to pin pnpm (corepack), so any vendored pnpm 12 project with a pinned pnpm hits this. Adding packageManager to an already vendored project (or upgrading to pnpm 12 with it set) turns every unwind path into a silent, partial revert that breaks CI's frozen install. Two of those paths (vendor --revert and the default scan) exit 0 with success.
Repro
Needs pnpm 12.8.1, a socket-patch built from main, and a patch API serving a free patch for [email protected]. A local mock of /v0/orgs/<org>/patches/{batch,package,view,by-package} and the hosted tarball was used, with SP="socket-patch … --api-url <mock> --org test-org --api-token fake".
set -u; W=$(mktemp -d); cd $W
echo '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > package.json
$PNPM install --store-dir $W/.store >/dev/null
$SP scan --mode vendored --json --yes --cwd . >/dev/null 2>&1 && echo "1. vendored on single-doc lock: ok"
node -e 'const f="package.json",p=require("./"+f);p.packageManager="[email protected]";require("fs").writeFileSync(f,JSON.stringify(p,null,2))'
$PNPM install --store-dir $W/.store >/dev/null
echo "2. lock documents: $(grep -c '^---$' pnpm-lock.yaml)"
cp -r $W $W.copy
$SP vendor --revert --json --yes --cwd . > revert.json 2>/dev/null; echo "3. vendor --revert exit=$? status=$(node -p 'require("./revert.json").status')"
echo " package.json overrides left: $(grep -c overrides package.json); pnpm-workspace.yaml: $(test -f pnpm-workspace.yaml && echo kept || echo deleted); lock file:.socket refs left: $(grep -c 'file:.socket' pnpm-lock.yaml)"
rm -rf node_modules; $PNPM install --frozen-lockfile --store-dir $W/.store2 2>&1 | grep -o 'ERR_PNPM_[A-Z_]*' | head -1
cd $W.copy; $SP scan --json --cwd . > s.json 2>/dev/null; echo "4. plain scan (takeover) exit=$? status=$(node -p 'require("./s.json").status') redirected=$(node -p 'require("./s.json").redirect.redirected')"
rm -rf node_modules; $PNPM install --frozen-lockfile --store-dir $W/.store3 2>&1 | grep -o 'ERR_PNPM_[A-Z_]*' | head -1
Output (identical on two runs):
1. vendored on single-doc lock: ok
2. lock documents: 2
3. vendor --revert exit=0 status=success
package.json overrides left: 0; pnpm-workspace.yaml: deleted; lock file:.socket refs left: 5
ERR_PNPM_OUTDATED_LOCKFILE
4. plain scan (takeover) exit=0 status=success redirected=0
ERR_PNPM_OUTDATED_LOCKFILE
For symptom 1, vendor straight onto the two-doc lock: create the project with packageManager already set, run pnpm install, then scan --mode vendored. It exits 1 with download.patches[0].errorCode = "vendor_lock_entry_not_found".
Expected vs actual
- Expected: the vendored planners address the document that holds the project lock (the one with the root importer's
dependenciesand thesettings:header). That would make vendor, revert, rollback and takeover behave exactly as they do on the single-doc lock. A single-doc control on the same pnpm 12.8.1 passes: vendor, then rollback, gives a byte-exact lock, and the takeover givesredirected: 1with a fresh frozen install landing the patched bytes. Failing that, the planners should refuse up front (fail closed) rather than half-revert. - CLI_CONTRACT.md (rollback JSON,
vendoredKept): "Drift-keeps — wiring drifted, vendored state (and the manifest entry) left untouched". Here the state is edited even though it's reported as kept, andvendor --revertreportssuccesson a revert that left the lock wired to the artifact. formats/pnpm/mod.rs:290documents the assumption: "pnpm 9-12 emitlockfileVersion: '9.0'(single doc, first line)".
Matrix (Linux, Node 22, main 2463257)
| pnpm | packageManager set |
lock docs | vendor | vendor --revert / rollback | default-scan takeover | hosted |
|---|---|---|---|---|---|---|
| 12.8.1 | yes | 2 | fail (vendor_lock_entry_not_found) |
fail (half-revert, frozen install broken) | fail (exit 0, ledger lost, frozen install broken) | pass |
| 12.8.1 | no | 1 | pass | pass | pass | pass |
| 11.28.3 | yes | 1 | pass | not run | not run | not run |
| 10.34.5 | yes | 1 | not run (single doc) |
macOS and Windows weren't probed; the logic is OS-independent line splicing. First bad release: not bisected. Release 4.0.0 can't run against the v5-shaped mock, and v5 (#277) introduced the default-hosted takeover.
Suspect code
crates/socket-patch-core/src/formats/pnpm/lines.rs:14section_boundstakes the firstname:header in the file and ignores---document separators.crates/socket-patch-core/src/vendor/pnpm_lock.rs:509(preflight_package→lock_has_target_package_in, line 1285) and the revert path that emitsvendor_lock_entry_drifted. Every section lookup runs against document 1, but theoverrides:lookup succeeds in document 2.crates/socket-patch-core/src/formats/pnpm/mod.rs:290: the single-document assumption.
Side note (not filed separately): pnpm 12 prints The "pnpm" field in package.json is no longer read by pnpm … "pnpm.overrides" on every install of a vendored project. The workspace-file override is what takes effect, so this is noise only.
- Vorherrschende Sprache
- Rust
- Sterne
- 8
- Forks
- 0
- Ø Merge
- 18 Std. 4 Min.
- Gemergte PRs (30 T.)
- 70
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus SocketDev/socket-patch
-
agent:triaged bug bughunt pm:composer priority:p2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 90/100
SocketDev/socket-patch#515 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
agent:triaged bug bughunt pm:npm priority:p1
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
SocketDev/socket-patch#464 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
agent:triaged bug bughunt pm:npm priority:p1
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
SocketDev/socket-patch#433 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
agent:triaged bug bughunt pm:uv priority:p1
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
SocketDev/socket-patch#408 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
SocketDev/socket-patch#370 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in SocketDev/socket-patch
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag