Repository navigation
Vendored uv transitive package: after uv remove of its parent, scan --prune, vendor --revert, remove and rollback drift-keep it, so vendor --check stays red and its prune remedy loops (project and script lanes) #1287
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:uvuvuv
on Oct 9, 2026 - added a commit that references this issue
on Oct 9, 2026 - addedv5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.Must resolve before v5: public interface/migration or ordinary patch-install-undo failure.uxCLI commands, help, diagnostics, output consistency, or actionable recovery instructions.CLI commands, help, diagnostics, output consistency, or actionable recovery instructions.compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.Public CLI/JSON, saved state, upgrades, or package-manager compatibility.
on Oct 9, 2026 mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actionsv5 release blocker (P1). A normal uv remove of a direct dependency must not strand its vendored transitive dependency and leave vendor --check permanently red. Give the ordinary project lane a cleanup path that actually works.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actions[agent] Claiming for v5 blocker burn-down (shared root cause: uv revert treats the vanished transitive [[package]] fragment as drift while socket-written override/source records still reference the uuid). Branch: agent/v5-uv-transitive-drift. Claim-ID: 20261009T164156Z-ddbaa5
- added a commit that references this issue
on Oct 9, 2026 mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actions[agent] uv bug-hunt run 37 (ledger #310): this still reproduces on main
85105c9. I checked PR #1337 (90c618a) on Linux with uv 0.5.31 and 0.12.24. The parent was a main dependency,--dev, or--group lint. Afteruv remove <parent>I ran each ofvendor --revert,remove six,rollbackandscan --mode vendored --prune. That's 24 cells, and all of them converge on the PR: exit 0, check 0, wheel gone, no uuid left,uv sync --lockedok. The user's ownconstraint-dependencies = ["six==1.16.0"]and[manifest] constraintsspecifier come back intact. The PEP 723 script lane also converges.One neighbour is not covered by the PR. If the user re-adds
six==1.16.0as a direct dependency, the revert half-reverts the pair. That happens after removing the parent and also with the parent kept. I filed it separately as #1374.
Generated by Claude Code
[agent] Found by the scheduled uv bug-hunt routine (ledger #310).
Summary
When the vendored package is transitive, vendored uv mode wires it through
[tool.uv] override-dependencies = ["six==1.16.0"]plus[tool.uv.sources] six = { path = ".socket/vendor/pypi/<uuid>/…whl" }, and uv.lock's[manifest] constraints / overrides. If the user later runsuv remove python-dateutil(the parent that pulled six in), uv drops six's[[package]]entry, but it never touches[tool.uv], so the socket-written override and source (and the manifest lines) stay. The "removed, not drift" rule from #1147 (projects) and #1231 (scripts) fires only when no wired file contains the uuid any more. Here the leftover sources/override still contain it, so the vanished[[package]]fragment is reported asvendor_lock_entry_driftedand the whole revert is kept.The result is the same stuck loop #1140 / #1214 fixed for direct packages:
vendor --checkexits 1 with "dependency removed: no lockfile resolves pkg:pypi/six@1.16.0 any more … runsocket-patch scan --mode vendored --prune", that prune exits 0 and changes nothing, and check stays red.Impact
A CI gate on
vendor --checkstays red for good after a routineuv removeof a direct dependency. Every remedy the tool names either exits 0 without doing anything or exits 1. The dead wheel, the ledger entry and the socket-writtenoverride-dependencies/sourceslines stay committed, and the override goes on pinningsix==1.16.0to the vendored wheel if anything pulls six back in later. Nothing installs unpatched.Repro (Linux, main
e9be746, uv 0.5.31 and 0.12.24)Patch data came from a local mock of the patch API (
six@1.16.0), the same one used for earlier uv issues.The PEP 723 script lane behaves the same way: a script with
dependencies = ["python-dateutil==2.8.2", "attrs>=20"]and# [tool.uv]/# constraint-dependencies = ["six==1.16.0"], run throughuv lock --script s.py, vendored, thenuv remove --script s.py python-dateutil.Expected vs actual
[[package]]record has nothing left to restore (vendor_lock_entry_removed), the pyproject / script[tool.uv]records that socket-patch wrote (override-dependencies,sources.six) and the uv.lock[manifest]records are unwound to the recorded originals, the wheel and ledger entry are deleted, andvendor --checkturns green. CLI_CONTRACT.md hasscan --prunerevert vendored entries whose dependency is gone, and that's the remedyvendor --checknames.Matrix (Linux, real
uv lock/uv remove, fresh fixture per cell)scan --prunevendor --revertremoverollbackvendor --checkafteruv remove python-dateutil)uv remove --script s.py python-dateutil)uv remove --script s.py six(#1214)macOS / Windows not probed: this is uuid text matching with no OS-specific branch.
Suspect code
crates/socket-patch-core/src/vendor/pypi_uv.rs:832-852(revert_uv):unreferencedis true only when neither pyproject.toml nor uv.lock contains the uuid. For a transitive package, the vendor-written[tool.uv.sources]/override-dependenciesand the[manifest]lines surviveuv remove <parent>, soremoved()never fires for the missing[[package]]record.crates/socket-patch-core/src/vendor/pypi_lock.rs:737-754(revert_python_locks): the same global check for script locks.A narrower rule may work: a record is "removed" when its own fragment (the
[[package]]entry for the key) is gone and the only surviving uuid references are fragments this ledger entry itself wrote and can restore. Those surviving records would then be reverted normally.Related: #1140 / #1214 (direct-package removal, fixed), #1285 (two scripts, one drops six).