pypa/pip · error · UnsupportedWheel
Error decoding metadata for {self._wheel_name}: {e} in {name
Error message
Error decoding metadata for {self._wheel_name}: {e} in {name} file What it means
UnsupportedWheel raised by InMemoryMetadata.get_metadata() (pkg_resources backend) when a metadata file's bytes cannot be decoded (UnicodeDecodeError). Mirrors the importlib-backend equivalent: the wheel is a valid zip but a metadata file is not decodable as text.
Source
Thrown at src/pip/_internal/metadata/pkg_resources.py:68
class InMemoryMetadata:
"""IMetadataProvider that reads metadata files from a dictionary.
This also maps metadata decoding exceptions to our internal exception type.
"""
def __init__(self, metadata: Mapping[str, bytes], wheel_name: str) -> None:
self._metadata = metadata
self._wheel_name = wheel_name
def has_metadata(self, name: str) -> bool:
return name in self._metadata
def get_metadata(self, name: str) -> str:
try:
return self._metadata[name].decode()
except UnicodeDecodeError as e:
# Augment the default error with the origin of the file.
raise UnsupportedWheel(
f"Error decoding metadata for {self._wheel_name}: {e} in {name} file"
)
def get_metadata_lines(self, name: str) -> Iterable[str]:
return pkg_resources.yield_lines(self.get_metadata(name))
def metadata_isdir(self, name: str) -> bool:
return False
def metadata_listdir(self, name: str) -> list[str]:
return []
def run_script(self, script_name: str, namespace: str) -> None:
pass
class Distribution(BaseDistribution):
def __init__(self, dist: pkg_resources.Distribution) -> None:View on GitHub (pinned to d7d0d0a394)
Solutions
- Rebuild the wheel with a current backend that emits UTF-8 metadata.
- Re-download the wheel from PyPI (verify hash) to rule out corruption.
- Install from sdist (--no-binary) to bypass the wheel.
- Report to the maintainer if a published wheel is affected.
Example fix
# before pip install somepkg-1.0-py2.py3-none-any.whl # legacy latin-1 METADATA # after pip install --no-binary somepkg somepkg # or rebuild python -m build --wheel
Defensive patterns
Strategy: validation
Validate before calling
import zipfile
with zipfile.ZipFile(wheel_path) as zf:
info_dir = next(n.split('/')[0] for n in zf.namelist() if n.endswith('.dist-info/METADATA'))
data = zf.read(f'{info_dir}/METADATA')
try:
data.decode('utf-8')
except UnicodeDecodeError:
print(f'METADATA in {wheel_path} not UTF-8') Type guard
def wheel_metadata_decodable(path: str) -> bool:
import zipfile
try:
with zipfile.ZipFile(path) as zf:
for n in zf.namelist():
if n.endswith(('.dist-info/METADATA', '.dist-info/WHEEL')):
zf.read(n).decode('utf-8')
return True
except (UnicodeDecodeError, zipfile.BadZipFile):
return False Try / catch
from pip._internal.exceptions import UnsupportedWheel
try:
dist = Distribution.from_wheel(wheel, name)
except UnsupportedWheel as e:
if 'decoding metadata' in str(e):
# rebuild/re-download wheel; fall back to sdist
... Prevention
- Build wheels with UTF-8 metadata using current backends.
- Verify hashes after download to catch corruption.
- Use --no-binary to build from sdist for legacy wheels.
- Report published wheels with non-UTF-8 metadata.
When it happens
Trigger: Reached when get_metadata(name) calls self._metadata[name].decode() and the bytes are not valid UTF-8 (default decode). The wheel name and offending file are included in the message.
Common situations: A legacy wheel whose METADATA/entry_points were written in a non-UTF-8 encoding; a corrupt wheel; a wheel produced by an old setuptools on a non-UTF-8 locale.
Related errors
- Error decoding metadata for {wheel}: {e} in {filename} file
- error decoding {path!r}: {e!r}
- payload in an invalid encoding
- Bad metadata in {dist} (invalid metadata entry 'name')
- Wheel '{name}' located at {location} is invalid.
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/cda59a7c56353c28.json.
Report an issue: GitHub.