# Your wheel can be a valid zip and still break installers. I built a checker for that.

> Source: <https://dev.to/haoli/your-wheel-can-be-a-valid-zip-and-still-break-installers-i-built-a-checker-for-that-1baf>
> Published: 2026-10-04 07:21:35+00:00

A 5.8 GiB PyTorch ROCm nightly wheel failed to install under uv with `zip64 extended information field was too long` ([astral-sh/uv#19440](https://github.com/astral-sh/uv/issues/19440)). Separately, `wheel tags` in wheel 0.47.0 was silently writing illegal ZIP64 structures into retagged wheels ([pypa/wheel#692](https://github.com/pypa/wheel/issues/692)).

Both are the same class of problem: the ZIP64 extra field (`0x0001`) in the file doesn't match what APPNOTE 4.5.3 requires. Python's `zipfile` reads these files fine — it silently tolerates the malformation — and then a stricter installer falls over.

I parse local file headers and central directory entries by hand (not trusting `zipfile`) and validate:

`0xFFFFFFFF`. This is exactly what wheel 0.47.0 did: an 8-byte ZIP64 extra in headers whose 32-bit sizes were perfectly fine.
I reproduced the wheel#692 MRE (lowering `zipfile.ZIP64_LIMIT` to force the ZIP64 path on small files, as the issue suggests), built a wheel, and retagged it:

| artifact | zipgate verdict | 
|---|---|
| original wheel | VALID | 
| retagged with wheel 0.47.0 | **INVALID** —`SPURIOUS_ZIP64_LOCAL` on two entries | 
| retagged with wheel 0.48.0 | VALID | 

The 0.47.0 output trips the exact rule the issue describes; 0.48.0 is clean.

```
pip install zipgate
zipgate dist/*.whl
```

Exit `0` = all valid, `1` = at least one invalid, `2` = unreadable. Eight tests, byte-level fixtures for both incident classes.

Repo: [hahahahahahahahah6/zipgate](https://github.com/hahahahahahahahah6/zipgate) (MIT).

If you ship wheels — especially big ones, or retagged ones — it's worth one command before upload.
