Repository navigation
Hosted rollback, remove and vendored takeover always refuse on a uv pip compile pylock.toml because its packages carry no index key #407
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 1, 2026 mikolalysenko commented
on Oct 1, 2026 CollaboratorAuthorMore actions[agent] Triaged:
priority:p1(uv). Not a duplicate, and no open or merged PR covers it.Shares root cause with #408:
lock_shape/render_artifactincrates/socket-patch-core/src/patch/redirect/upstream/uv.rsapply uv.lock rules to PEP 751 pylock files. They take the registry only from anindexkey (whichuv pip compilenever writes) and formatupload-timewith uv.lock's millisecond precision (pylock uses whole seconds). The fix is to read the pylock siblings' own shape: infer the registry from their PyPI artifact URLs and follow theirupload-timeprecision. Will be fixed together.
Generated by Claude Code
mikolalysenko commented
on Oct 1, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue (with #408; shared root cause: the PEP 751 upstream restore in
upstream/uv.rsapplies uv.lock rules to pylock files: registry only fromindex, millisecondupload-time). Branch: agent/fix-uv-pylock-restore-shape. Claim-ID: 2026-10-01T23:20:47Z-0e9aae
Generated by Claude Code
mikolalysenko commented
on Oct 1, 2026 CollaboratorAuthorMore actions- added 2 commits that reference this issue
on Oct 2, 2026 mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] From the Hatch bug-hunt routine (ledger #314): Hatch's own locker also produces this pylock shape, so every locked Hatch project hits this too.
On main
61cfb9bwith real Hatch 1.17.0 and 1.18.1:[tool.hatch.envs.default] locked = true, installer = "uv"withdependencies = ["six==1.16.0", "idna==3.7", "certifi==2024.8.30"], thenhatch lock. The resultingpylock.toml(created-by = "uv") has 3[[packages]]and noindexkey. Thenscan --mode hostedrewrites six to anarchiveentry, and after that (two runs per version):rollback→partial_failure:pylock.toml: no sibling registry package shows the registry and artifact fields this uv release records; restore it from version control insteadremove pkg:pypi/six@1.16.0→hosted_revert_failed(same message)scan --mode vendored --vendor-source service(hosted → vendored takeover) →redirect_revert_failed
The vendored rollback / remove on the same project succeed. (The fact that only the lock gets wired on these projects is tracked separately in #479.)
Generated by Claude Code
[agent] Found by the scheduled uv bug-hunt routine (ledger #310).
Summary
A standalone PEP 751 lock made by
uv pip compile --format pylock.tomlis a supported hosted lane (docs/testing/uv-compatibility.md, "standalone PEP 751 compilation").scan --mode hostedwires it, anduv pip sync pylock.tomlinstalls the patch. But on main the hosted pin can't be unwound by anything:rollback→partial_failure:cannot restore pkg:pypi/six@1.16.0 to its upstream registry entry: pylock.toml: no sibling registry package shows the registry and artifact fields this uv release records; restore it from version control instead (git checkout -- pylock.toml)remove pkg:pypi/six@1.16.0→hosted_revert_failed(same message)scan --mode vendored(hosted → vendored takeover) →failed redirect_revert_failedThe cause:
uv pip compilenever writes anindexkey on[[packages]](onlyuv export --format pylock.tomldoes). The v5 upstream restore takes a pylock entry's registry only from a sibling'sindex(crates/socket-patch-core/src/patch/redirect/upstream/uv.rs:314-321). With no sibling carrying one,registriesis empty and the restore refuses, however many plain PyPI siblings the lock has. Every sibling here is afiles.pythonhosted.orgartifact with the fullurl/upload-time/size/hashesshape.Impact
Any project that uses
uv pip compile --format pylock.tomland adopts hosted mode can't roll back, remove or switch to vendored mode afterwards. The only remedy is thegit checkoutthe error suggests, which also throws away any unrelated lock changes made since. Arollbackmeant to unpatch everything leaves the patch wired and installable.Repro (Linux)
Mock patch API as in #379 / #381 (now also returning
integrity.sha512),--patch-server-urlfor the mock origin, PyPI JSON API reachable.Control: the same packages exported with
uv lock && uv export --format pylock.toml(which writesindex = "https://pypi.org/simple") roll back successfully.Expected vs actual
rollback/removerestore PEP 751pylock*.tomlpins, with hashes re-derived from PyPI's JSON API. The listed refusals for pylock are only "a release with a wheel that is not pure Python 3". The "other registry packages name no registry" refusal is stated for uv locks, where every registry package records its source. For auv pip compilepylock the missingindexis normal, so the restore should follow the siblings' shape (noindexkey) when their artifacts are PyPI files. At minimum, the refusal should be documented, and hosted mode should warn before it wires a lock it can never unwind.uv pip compilepylock, and the hosted pin stays.OS × uv matrix (main
2463257)macOS and Windows weren't probed. The refusal is in platform-independent TOML inspection.
First bad
2463257(#277, the v5 upstream restore; v4's ledger-based revert didn't depend on sibling entries).Suspect code
crates/socket-patch-core/src/patch/redirect/upstream/uv.rs:314-321: forpep751, the registry comes only frompackage.get("index"), and siblings without it are skipped.crates/socket-patch-core/src/patch/redirect/upstream/uv.rs:345-351: the "no sibling registry package" refusal.Related, separate: the restored entry's
upload-timeprecision on exported pylocks (filed separately).