Repository navigation
Vendored vlt scan exits 1 after the patched dependency is upgraded or uninstalled, and even scan --prune exits 1 while it reverts the stale entry #541
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:vltvltvlt
on Oct 2, 2026 - added a commit that references this issue
on Oct 2, 2026 mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] Triaged as
priority:p1(vlt is in the npm family). It isn't a duplicate, and I found no open or merged PR that fixes it.On main
61cfb9b,vendored_ledger_supplement(crates/socket-patch-cli/src/commands/scan/discovery.rs:141) adds back every ledger entry that has no crawled counterpart. It never checks whether the lock still wires that entry (the prune GC does this check throughdispatch_in_use_one). The issue says the npm package-lock path hits the same code. A fix belongs in the shared supplement, so it covers every ecosystem and not just vlt.
Generated by Claude Code
mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue. Shared root cause: the vendored ledger supplement re-adds entries the lock no longer wires. Branch: agent/fix-vendored-supplement-unwired. Claim-ID: 2026-10-02T08:21:03Z-2b345a
Generated by Claude Code
mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actionsmikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] Scope note for #543. That PR fixes the shared ledger-supplement cause: vlt rescans and
--pruneexit 0 after a bump or uninstall, and the npm package-lock rescan exits 0 too. It doesn't change the npm prune behavior this issue mentions (revertedVendoredEntries: []). When an npm uninstall re-locks the vendored entry away, the GC drift-keeps it on purpose (scan_prune_reverts_unused_vendored_entryasserts this). That entry then keeps getting the newvendor_ledger_entry_unwiredwarning, and neithervendor --revertnorremove <purl>clears it per package. Settling whether an entry whose lock entry vanished (with nothing left referencing its artifact) should be reclaimed is the separate npm follow-up.
Generated by Claude Code
mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] vlt bug-hunt routine (ledger #307): I checked draft PR #543 (head
11934b9) against real vlt installs on Linux, with a local mock registry and patch server.vlt case main 61cfb9b: rescan /--prune/ rescan#543: rescan / --prune/ rescan1.3.5 vlt install left-pad@1.2.0after vendoring1 / 1 / 0 ( vendor_lock_entry_not_found)0 / 0 / 0 ( vendor_ledger_entry_unwiredwarning)1.3.5 vlt uninstall left-padafter vendoring1 / 1 / 0 0 / 0 / 0 1.2.0 bump 1 / 1 / 0 0 / 0 / 0 1.2.0 uninstall 1 / 1 / 0 0 / 0 / 0 In every cell,
--pruneempties.socket/vendor/npm, and the installed package stays on the version the user chose (olderafter the bump, and absent after the uninstall). On vlt, #543 fixes the exit codes this issue reports. I haven't tested macOS or Windows yet.
Generated by Claude Code
- added a commit that references this issue
on Oct 2, 2026
[agent] Found by the scheduled vlt bug-hunt routine (ledger #307).
Summary
Say a vlt project vendors
left-pad@1.3.0(scan --mode vendored), and then the dependency leaves the lock in the usual way: it's bumped toleft-pad@1.2.0andvlt installruns, orvlt uninstall left-padruns. After that, everysocket-patch scan --mode vendoredexits 1 withpartial_failure/vendor_lock_entry_not_foundand tells the user to "runvlt installfirst", which they already did.The documented way out is
scan --prune. It does revert the stale ledger entry (gc.revertedVendoredEntries: ["pkg:npm/left-pad@1.3.0"], and.socket/is gone afterwards), but the same run still exits 1. It reports the purl it just reconciled as a failed vendor. Only the run after that one exits 0.The cause:
vendored_ledger_supplementadds every ledger entry that has no crawled counterpart back into discovery. The intent is "on a fresh clone the committed artifact IS the dependency", but the function never asks whether the lock still wires that artifact. The vendor step then tries to re-vendor a package the lock no longer has. It does this before the prune GC runs, which is the documented order.Impact
scan --mode vendored(a cron or CI job) goes red permanently after any routine dependency upgrade or removal. The error points users at the wrong fix (vlt install).scan --mode vendored --prune, the documented reconcile, still fails the one run that actually reconciles. CI can't tell a real vendor failure from a successful cleanup.installed content differs from patch baseline; the patched content will be vendoredforleft-pad@1.3.0, because the supplement points the path atnode_modules/left-pad, which is now 1.2.0.Repro (Linux, vlt 1.3.5, main
61cfb9b)The local mock registry and patch API are the ones described in the ledger (#307). Any registry with
left-pad@1.3.0and@1.2.0plus a patch for 1.3.0 works.Human output of the
--prunerun:The
vlt uninstall left-padvariant behaves the same way (rescan rc 1, prune rc 1 and reverts, next run rc 0).Expected vs actual
scan --prunereconciles ledger entries whose dependency left the lockfile", and the prune's leg (b) reverts "EVERY ledger entry whose dependency is no longer in the lockfile graph". A run that does exactly that should exit 0, perhaps with a warning. It shouldn't reportpartial_failurefor the entry it reconciled.--prune) rather than fail with advice to runvlt install.--pruneruns, and the--prunerun itself fails with exit 1.Matrix (Linux; macOS / Windows untested because probe branches are blocked this run)
--prunevlt uninstallnpm control on the same mock (package-lock v3): the bump → rescan also exits 1.
--prunethere doesn't revert at all (revertedVendoredEntries: []) and stays at rc 1, so npm users stay stuck. I've passed that to the npm routine's ledger separately. The supplement/ordering part is shared code.First bad release: none. Release 4.0.0 predates vendored vlt support, so this is unreleased main behaviour.
Suspect code
crates/socket-patch-cli/src/commands/scan/discovery.rs:141:vendored_ledger_supplementsupplements ledger entries without checking that the lock still wires them (dispatch_in_use_one,crates/socket-patch-cli/src/commands/vendor.rs:260, already answersSome(false)here; the prune GC uses it).crates/socket-patch-cli/src/commands/scan/mod.rs:1626: the call site. The vendor step runs before the prune GC.crates/socket-patch-core/src/vendor/vlt_lock.rs:475: the refusal and its misleading hint.