GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Hosted rollback and remove always refuse a `pip lock` pylock.toml ("no sibling registry package shows the registry and artifact fields"), because pip writes `[[packages.wheels]]` tables, not uv's inline `wheels = [...]` · Issue #804 · SocketDev/socket-patch

Hosted rollback and remove always refuse a pip lock pylock.toml ("no sibling registry package shows the registry and artifact fields"), because pip writes [[packages.wheels]] tables, not uv's inline wheels = [...] #804

New issue
Copy link
New issue
Copy link
Closed
#807
Closed
Hosted rollback and remove always refuse a pip lock pylock.toml ("no sibling registry package shows the registry and artifact fields"), because pip writes [[packages.wheels]] tables, not uv's inline wheels = [...]#804
#807
Copy link
Labels
agent:triagedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:pippip / requirements.txtpip / requirements.txtpriority:p1

Description

@mikolalysenko
Mikola Lysenko (mikolalysenko)
opened on Oct 4, 2026
Issue body actions

[agent] Found by the scheduled pip / requirements.txt bug-hunt routine (ledger #309).

Summary

pip lock (pip 25.1+) writes a PEP 751 pylock.toml, and pip 26.1+ installs from it with pip install -r pylock.toml. Unlike uv, pip writes each artifact as an array of tables:

[[packages]]
name = "idna"
version = "3.7"

[[packages.wheels]]
name = "idna-3.7-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/…/idna-3.7-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "82fe…"

scan --mode hosted handles this file fine. It rewrites six to archive = { url = <hosted wheel>, hashes = … }, and pip 26.2.1 installs the patched wheel from it. But the upstream restore can't read pip's shape: artifact_tables and the shape probe only accept an inline wheels array. Every sibling (here, idna with only files.pythonhosted.org wheels) is then skipped as "not a registry package". So rollback and remove always refuse:

cannot restore pkg:pypi/[email protected] 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`)

They exit 1 (partial_failure / hosted_revert_failed), and rollback --dry-run predicts the same failure. The same lock with the same siblings written as inline wheels = [{…}] rolls back with exit 0 (control below). This is a new shape, not #407: #407 (fixed) was the uv pip compile pylock that has no index. pip's lock has no index either, and that part is now handled, but its siblings are never recognised.

Impact

On any project that uses pip's own lock format, a hosted patch can be applied but never unpatched with socket-patch rollback / remove, the same class as #410 for requirements.txt. The error message also blames "this uv release" for a file that created-by = "pip" wrote. The hosted → vendored takeover goes through the same upstream restore and is probably refused too; I haven't verified that.

Repro (Linux, main 045d7ec)

The hosted API is a local wiremock: the mount_hosted_api routes from crates/socket-patch-cli/tests/mode_migration_pypi.rs, served by a throwaway, uncommitted driver. The upstream restore uses the real PyPI JSON API.

python3 -m venv v && v/bin/pip install pip==26.2.1     # also: pip==25.1, 25.3, 26.0 (same file shape)
printf 'six==1.16.0\nidna==3.7\n' > requirements.txt
v/bin/pip lock -r requirements.txt -o pylock.toml       # created-by = "pip", [[packages.wheels]] tables
rm requirements.txt
F="--yes --patch-server-url $MOCK"
socket-patch scan --mode hosted --json --api-url $MOCK --org test-org --api-token fake $F
#   exit 0, redirected 1, six -> archive = { url = "$MOCK/patch/pypi/six/1.16.0/…/six-1.16.0-py2.py3-none-any.whl", hashes = … }
python3 -m venv f && f/bin/pip install pip==26.2.1 && f/bin/pip install -r pylock.toml   # installs the patched six (ok)
socket-patch rollback $F                         # exit 1: "no sibling registry package shows the registry and artifact fields this uv release records"
socket-patch remove pkg:pypi/[email protected] $F       # exit 1: hosted_revert_failed, same message
socket-patch rollback --dry-run --json $F        # partial_failure, same message

Control: rewrite the same original lock with inline wheels = [{ name, url, hashes }] for both packages. scan --mode hosted then rollback exits 0 with hosted.reverted: ["pkg:pypi/[email protected]"].

Reproduced twice: once on a pip 26.2.1 lock and once on a separate project with a pip 25.1 lock.

Expected vs actual

CLI_CONTRACT.md (the rollback upstream-restore list) refuses only a pylock "whose other registry packages show neither an index nor (as uv pip compile writes them) only PyPI files with none, which restores the entry without an index too". The pip lock's sibling has no index and only PyPI files, so it should restore without an index. PEP 751 allows both TOML spellings of packages.wheels.

Expected: rollback / remove restore six's [[packages.wheels]] entry from PyPI (in the siblings' array-of-tables shape) and exit 0. Or, if that shape isn't supported, scan --mode hosted should refuse it up front instead of writing a patch it can't undo. Actual: the scan succeeds, and every rollback / remove exits 1.

OS × version

OS pip that wrote the lock hosted scan + pip install -r pylock.toml rollback / remove
Linux 26.2.1 (py3.11) pass (pip 26.2.1 installs the patched wheel) fail
Linux 25.1 (py3.11) pass (scan; pip < 26.1 can't install a pylock) fail
Linux 25.3, 26.0 same [[packages.wheels]] shape (not run end to end) expected fail
macOS / Windows — not probed (TOML parsing only, OS-independent) not probed

First bad version

Not bisected. The array-of-tables shape has never been readable: the restore was written against uv's inline output, and the only [[packages.wheels]] fixture in the repo (tests/e2e_vex_lockfile/uv.rs:198) is a vex test.

Suspect code

  • crates/socket-patch-core/src/patch/redirect/upstream/uv.rs:328 artifact_tables: package.get("wheels").and_then(Item::as_array) (and sdist via as_value) returns nothing for an ArrayOfTables / standard table. So pylock_unindexed_registry (:353) returns None for every pip sibling.
  • uv.rs:407-426, the shape probe: same as_array / as_inline_table assumption.
  • uv.rs:442: the resulting refusal, worded for uv.

Activity

  1. Mikola Lysenko (mikolalysenko)
    added
    bugSomething isn't workingSomething isn't working
    bughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agent
    pm:pippip / requirements.txtpip / requirements.txt
    on Oct 4, 2026
  2. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 4, 2026
    CollaboratorAuthor
    More actions

    [agent] Verified the hosted → vendored takeover too (main 045d7ec, a pip 26.2.1 lock). After scan --mode hosted, scan --mode vendored exits 1 (partial_failure, redirect_revert_failed: "cannot vendor over the live hosted pin: cannot restore pkg:pypi/[email protected] to its upstream registry entry: pylock.toml: no sibling registry package shows …"), and the hosted archive stays in place.

    For contrast, plain vendored mode over the same pip lock file works. It writes archive = { path = ".socket/vendor/pypi/<uuid>/six-1.16.0-py2.py3-none-any.whl", hashes = … }, pip 26.2.1 installs the patched wheel from it (both from the project root and with -r /abs/path/pylock.toml from another directory), a rescan is idempotent, and vendor --revert restores the file byte-identically. So only the hosted upstream restore misreads pip's [[packages.wheels]] shape.


    Generated by Claude Code

  3. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 4, 2026
    CollaboratorAuthor
    More actions

    [agent] Triaged as priority:p1 (PyPI / pip). Confirmed on main 045d7ec: artifact_tables in crates/socket-patch-core/src/patch/redirect/upstream/uv.rs:328 reads wheels only through Item::as_array and keeps only inline tables, so pip's [[packages.wheels]] array-of-tables siblings yield no artifacts and pylock_unindexed_registry returns None for every one. Not a duplicate of #407 (fixed by #512, which handled the missing index but not this TOML spelling). No open PR covers it.


    Generated by Claude Code

  4. Mikola Lysenko (mikolalysenko)
    added
    agent:triaged
    priority:p1
    on Oct 4, 2026
  5. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 4, 2026
    CollaboratorAuthor
    More actions

    [agent] Claiming this issue (shared root cause: the hosted pylock upstream restore reads packages.wheels only as an inline array, so pip's [[packages.wheels]] array-of-tables shape is invisible). Branch: agent/fix-pylock-wheels-table-array. Claim-ID: 2026-10-04T21:20:35Z-73c495


    Generated by Claude Code

  6. Mikola Lysenko (mikolalysenko)
    added
    agent:claimed
    on Oct 4, 2026
  7. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 4, 2026
    CollaboratorAuthor
    More actions

    [agent] Draft PR: #807


    Generated by Claude Code

  8. Mikola Lysenko (mikolalysenko)
    added a commit that references this issue on Oct 4, 2026

    Fix rollback of pip-written pylock.toml

    This issue will close once commit b33b0ed is merged into the 'main' branch.
    b33b0ed
  9. Mikola Lysenko (mikolalysenko)
    closed this as completedin #807on Oct 5, 2026
  10. mikolalysenko commented on Oct 5, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 5, 2026
    CollaboratorAuthor
    More actions

    [agent] Verified fixed on main 9c43dfc (PR #807) with real pip 26.2.1 on py3.11. I used a pip lock -r lock of six==1.16.0 + idna==3.7 (created-by = "pip", [[packages.wheels]] tables) and a local mock of the hosted API.

    • scan --mode hosted exits 0 and rewrites six to archive = { url = <hosted wheel>, hashes = … }. A fresh pip install -r pylock.toml imports the patched six.
    • rollback exits 0 with hosted.reverted: ["pkg:pypi/[email protected]"], and pylock.toml is byte-identical to the original pip lock output. A fresh pip install -r pylock.toml then gets the unpatched six.
    • remove pkg:pypi/[email protected] (after a fresh hosted scan) exits 0 with hosted_reverted, and the file is again byte-identical.

    Generated by Claude Code

  11. Mikola Lysenko (mikolalysenko)
    removed
    agent:claimed
    on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:pippip / requirements.txtpip / requirements.txtpriority:p1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.