pypa/pip · error · UnsupportedWheel
Error decoding metadata for {wheel}: {e} in {filename} file
Error message
Error decoding metadata for {wheel}: {e} in {filename} file What it means
UnsupportedWheel raised by WheelDistribution.read_text() when a metadata file inside the wheel (METADATA / WHEEL / entry_points etc.) cannot be decoded as UTF-8. The wheel is structurally a valid zip but its metadata bytes are not valid UTF-8, so importlib.metadata cannot parse it.
Source
Thrown at src/pip/_internal/metadata/importlib/_dists.py:93
return cls(files, info_location)
def iterdir(self, path: InfoPath) -> Iterator[pathlib.PurePosixPath]:
# Only allow iterating through the metadata directory.
if pathlib.PurePosixPath(str(path)) in self._files:
return iter(self._files)
raise FileNotFoundError(path)
def read_text(self, filename: str) -> str | None:
try:
data = self._files[pathlib.PurePosixPath(filename)]
except KeyError:
return None
try:
text = data.decode("utf-8")
except UnicodeDecodeError as e:
wheel = self.info_location.parent
error = f"Error decoding metadata for {wheel}: {e} in {filename} file"
raise UnsupportedWheel(error)
return text
def locate_file(self, path: str | PathLike[str]) -> pathlib.Path:
# This method doesn't make sense for our in-memory wheel, but the API
# requires us to define it.
raise NotImplementedError
class Distribution(BaseDistribution):
def __init__(
self,
dist: importlib.metadata.Distribution,
info_location: BasePath | None,
installed_location: BasePath | None,
) -> None:
self._dist = dist
self._info_location = info_location
self._installed_location = installed_locationView on GitHub (pinned to d7d0d0a394)
Solutions
- Re-download the wheel (verify its hash) in case of transfer corruption.
- Rebuild the wheel with a current build backend (build/hatch/setuptools>=64) that emits UTF-8 metadata.
- Report to the package maintainer if a published wheel ships non-UTF-8 metadata.
- Force a source install (--no-binary) to bypass the broken wheel.
Example fix
# before - install a wheel with latin-1 METADATA pip install somepkg-1.0-py3-none-any.whl # after pip install --no-binary somepkg somepkg # build from sdist # or rebuild the wheel correctly python -m build --wheel
Defensive patterns
Strategy: validation
Validate before calling
import zipfile
with zipfile.ZipFile(wheel_path) as zf:
for n in zf.namelist():
if n.endswith(('METADATA','RECORD','WHEEL','entry_points.txt')):
try:
zf.read(n).decode('utf-8')
except UnicodeDecodeError:
print(f'{n} in {wheel_path} is not UTF-8') Type guard
def wheel_metadata_utf8(path: str) -> bool:
import zipfile
try:
with zipfile.ZipFile(path) as zf:
for n in zf.namelist():
if n.endswith(('METADATA','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 or re-download the wheel
... Prevention
- Build wheels with UTF-8 locale and current backends.
- Verify wheel hashes after download to detect corruption.
- Use --no-binary to fall back to sdist for legacy wheels.
- Report non-UTF-8 metadata to package maintainers.
When it happens
Trigger: Reached while reading an in-memory wheel's metadata file: data.decode('utf-8') raises UnicodeDecodeError. The offending filename is included in the message along with the wheel location.
Common situations: A wheel built with a non-UTF-8 locale or an old tool that wrote metadata in latin-1/cp1252; a metadata file accidentally containing binary garbage; a corrupt wheel download producing non-UTF-8 bytes.
Related errors
- Error decoding metadata for {self._wheel_name}: {e} in {name
- error decoding {path!r}: {e!r}
- payload in an invalid encoding
- Bad metadata in {dist} (invalid metadata entry 'name')
- {name} has an invalid wheel, {e}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/0eac9f25c945dbe1.json.
Report an issue: GitHub.