pypa/pip · error · InvalidWheel
Wheel '{name}' located at {location} is invalid.
Error message
Wheel '{name}' located at {location} is invalid. What it means
InvalidWheel raised by Distribution.from_wheel() (pkg_resources backend) when wheel.as_zipfile() raises zipfile.BadZipFile, or when an UnsupportedWheel propagates and is re-wrapped. The .whl file is not a valid ZIP (or its internal structure is unparseable), so pkg_resources cannot construct the distribution.
Source
Thrown at src/pip/_internal/metadata/pkg_resources.py:149
dist = pkg_resources.DistInfoDistribution(
location=filename,
metadata=InMemoryMetadata(metadata_dict, filename),
project_name=project_name,
)
return cls(dist)
@classmethod
def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution:
try:
with wheel.as_zipfile() as zf:
info_dir, _ = parse_wheel(zf, name)
metadata_dict = {
path.split("/", 1)[-1]: read_wheel_metadata_file(zf, path)
for path in zf.namelist()
if path.startswith(f"{info_dir}/")
}
except zipfile.BadZipFile as e:
raise InvalidWheel(wheel.location, name) from e
except UnsupportedWheel as e:
raise UnsupportedWheel(f"{name} has an invalid wheel, {e}")
dist = pkg_resources.DistInfoDistribution(
location=wheel.location,
metadata=InMemoryMetadata(metadata_dict, wheel.location),
project_name=name,
)
return cls(dist)
@property
def location(self) -> str | None:
return self._dist.location
@property
def installed_location(self) -> str | None:
egg_link = egg_link_path_from_location(self.raw_name)
if egg_link:
location = egg_linkView on GitHub (pinned to d7d0d0a394)
Solutions
- Purge the cache (pip cache purge) and reinstall with --no-cache-dir.
- Verify the wheel hash against PyPI to detect corruption.
- Re-download directly from PyPI, bypassing mirrors/proxies.
- If the inner cause is an unsupported wheel, address that specific metadata issue once the file is valid.
Example fix
# before pip install ./somepkg-1.0-py3-none-any.whl # corrupt file # after pip cache purge pip install --no-cache-dir somepkg
Defensive patterns
Strategy: validation
Validate before calling
import zipfile
try:
with zipfile.ZipFile(path) as zf:
assert zf.testzip() is None
# also ensure a .dist-info exists
assert any(n.endswith('.dist-info/METADATA') for n in zf.namelist())
print('valid wheel')
except (zipfile.BadZipFile, AssertionError):
print('invalid wheel') Type guard
def is_valid_wheel(path: str) -> bool:
import zipfile
try:
with zipfile.ZipFile(path) as zf:
return zf.testzip() is None and any(
n.endswith('.dist-info/METADATA') for n in zf.namelist())
except zipfile.BadZipFile:
return False Try / catch
from pip._internal.exceptions import InvalidWheel, UnsupportedWheel
try:
dist = Distribution.from_wheel(wheel, name)
except InvalidWheel:
# purge cache, re-download
except UnsupportedWheel as e:
# inner metadata issue; address specifics
... Prevention
- Verify wheel hashes against PyPI before installing.
- Purge the pip cache when a corrupt file is suspected.
- Re-download with --no-cache-dir from PyPI directly.
- Avoid mirrors/proxies that may serve corrupt artifacts.
When it happens
Trigger: Reached while loading a wheel via the pkg_resources metadata backend: opening the file as a zip fails because it is truncated, corrupt, or not actually a zip. Also re-raises an inner UnsupportedWheel as 'X has an invalid wheel, ...'.
Common situations: Corrupted download, partial file in pip cache, a mirror/proxy serving an error page with a .whl extension, or a wheel whose dist-info structure is invalid (re-wrapped UnsupportedWheel).
Related errors
- Wheel '{name}' located at {location} is invalid.
- Bad metadata in {dist} (invalid metadata entry 'name')
- Error decoding metadata for {self._wheel_name}: {e} in {name
- could not read {path!r} file: {e!r}
- Too many arguments
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/922f5c6255a691e9.json.
Report an issue: GitHub.