Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

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

Offen
#466 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

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

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:triaged bug bughunt pm:pnpm priority:p1

[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:

  1. scan --mode vendored / vendor refuses wrongly. It reports vendor_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.
  2. vendor --revert on a project vendored before the lock became two-doc: exit 0, status: success. It removes pnpm.overrides from package.json, deletes the scaffolded pnpm-workspace.yaml and removes the lock's overrides: block. It leaves all 5 file:.socket/vendor/... references in the importers, packages and snapshots of document 2. Every event is skipped / vendor_lock_entry_drifted ("packages entry ... no longer exists"), which is false. The next pnpm install --frozen-lockfile fails with ERR_PNPM_OUTDATED_LOCKFILE.
  3. rollback does the same edits. It then reports vendoredKept: [{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.
  4. Plain scan (v5 default hosted mode) does a vendored→hosted takeover. It warns redirect_takeover_reverted_vendored, deletes the vendor ledger (.socket/vendor/state.json), package.json overrides, the workspace file and the lock overrides: block, then warns redirect_pnpm_entry_vendored with redirected: 0. It exits 0 with status: success. The project is left with no ledger, no hosted pin and a lock that --frozen-lockfile rejects (ERR_PNPM_OUTDATED_LOCKFILE). Because the ledger is gone, a later rollback can 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 dependencies and the settings: 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 gives redirected: 1 with 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, and vendor --revert reports success on a revert that left the lock wired to the artifact.
  • formats/pnpm/mod.rs:290 documents the assumption: "pnpm 9-12 emit lockfileVersion: '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:14 section_bounds takes the first name: 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 emits vendor_lock_entry_drifted. Every section lookup runs against document 1, but the overrides: 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

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus SocketDev/socket-patch

Alle Issues in SocketDev/socket-patch

Ähnliche Issues

Weitere Issues zu Rust

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.