Repository navigation
Skip orphaned pnpm store entries in vendored scan (#1197) - #1320
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
pnpm 7-11 keep a removed or upgraded-away package's node_modules/.pnpm/<name>@<version> entry for up to 7 days, and pnpm 12 keeps an upgraded-away one until `pnpm prune`. The scan walked every entry, so a vendored scan asked for the orphan's patch and failed it with vendor_lock_entry_not_found, exiting 1 on every run. The `pnpm install` remedy it printed did not help. The scan now reads the current lockfile pnpm writes in the store (.pnpm/lock.yaml, every lock generation) and skips an entry whose package it no longer lists, confirmed by the entry's package.json. With no current lockfile, or one naming a package it cannot read, nothing is dropped. Rollback and the resolver still reach orphans. Fixes #1197 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 9, 2026 17:56
Collaborator
Author
|
BugBot review |
Mikola Lysenko (mikolalysenko)
enabled auto-merge
October 9, 2026 17:56
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 4a80b72. Configure here.
The orphan filter read every store entry's package.json before checking the current lockfile, and parsed each lock entry's resolution it never used: the pnpm scan benchmarks (3000 packages) slowed by a third. A live registry entry now costs no read, and the lock is read in one line walk over its packages keys and name/version fields. A current lockfile listing no package (a stub, or a project with no dependencies left) now drops nothing, as it says nothing about which entries are live. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 9, 2026
Tanmay Singla (Tanmay182003)
approved these changes
Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1197
Summary
pnpm 7–11 keep a removed or upgraded-away package's
node_modules/.pnpm/<name>@<version>entry for up to 7 days (modules-cache-max-age). pnpm 12 keeps an upgraded-away one untilpnpm prune. Nothing links to the entry and neither lock lists it. The npm crawler still walked it, soscan --mode vendoredrequested its patch and failed it withvendor_lock_entry_not_found(partial_failure, exit 1) on every run. Thepnpm installremedy it printed doesn't remove the entry.The scan now skips these orphans. It reads pnpm's current lockfile, the
lock.yamlthat pnpm rewrites in its virtual store on every install, and drops an in-project (or relocated).pnpmentry whose package that file no longer lists:formats::pnpm::InstalledPackagesreads the current lockfile in every generation: v5.4/name/1.0.0, v6/name@1.0.0, v9name@1.0.0keys, peer suffixes stripped, andfile:/ url / git entries by theirname:/version:fields or the v9 key name. An entry with no version counts as "any version installed". If any entry can't be named, the result isNoneand nothing is dropped.orphaned_pnpm_store_entry_syncnames the entry, either from a registryname@versiondir or aname@file+…tarball dir, and confirms it against the entry'spackage.json. It drops the entry only when that(name, version)is not installed. An entry it can't name or read is kept.live_onlypath, as for Bun's orphans (With Bun's isolated linker,vexrefuses every hosted patch as not_applied after the usual in-placebun install, because it checks orphanednode_modules/.bunregistry entries that Bun never removes (regression from #496) #599). The resolver and peer-variant finder (rollback, remove) still reach orphans.Measured on real pnpm 7.33.7, 8.15.9, 10.34.6, 11.28.5 and 12.10.1 with
pnpm add -E left-pad@1.2.0over 1.3.0: theleft-pad@1.3.0dir stays in every version, andlock.yamllists onlyleft-pad@1.2.0, with the key shapes above. That covers the pnpm 12 upgrade path from the follow-up comment.crawler_npm_e2e::crawl_all_inventories_pnpm_virtual_store_exactly_once, whose fixture has a stublock.yaml.Root cause
list_pnpm_shaped_store_entries_syncenumerated every.pnpmentry with no reachability filter. Itslive_onlymode filtered only Bun stores, on the assumption that pnpm prunes on install, which pnpm doesn't do.Tests (red → green)
scan_vendor_e2e::exact_download_plan::vendored_scan_skips_a_pnpm_store_entry_the_install_dropped: a purl-aware batch mock and an orphaned.pnpm/pkg-y@1.0.0. Without the crawler change it fails withscannedPackages: 2,partial_failure, exit 1. With the change it exits 0,successnpm_crawler::tests::test_pnpm_store_entries_the_current_lockfile_drops_are_not_scannedcovers a removed entry, an upgraded-away entry, an old vendoredname@file+…entry, a live scoped vendored entry, v5.4/v6/v9 keys, the no-lock.yaml control and rollback reach. It failed before the fixformats::pnpm::tests::installed_packages_read_every_lock_generationCommands run
cargo fmt --all -- --check,cargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --lib: 6111 passed--test scan_vendor_e2e,e2e_vendor_pnpm_build,scan_pnpm_relocated_store_cwd_e2e,in_process_vendor_pnpm_takeover,in_process_vendor_pnpm_parent_child,e2e_redirect_pnpm_build,e2e_yarn4_pnpm_linker_build: all passDocs: docs/ecosystems.md (crawl section).
🤖 Generated with Claude Code