pypa/pip · error · NoneMetadataError
None metadata found for distribution
Error message
None {metadata_name} metadata found for distribution: {dist} What it means
In the legacy resolver, _check_metadata_requires_python reads dist.requires_python (resolver.py:78-80); if accessing it raises FileNotFoundError, pip wraps it as NoneMetadataError. This signals an inconsistency: the distribution claims metadata exists but the METADATA/PKG-INFO file is missing or unreadable.
Solutions
- Reinstall the offending package to restore its METADATA file.
- Fix filesystem permissions on the site-packages/dist-info directory.
- Remove the corrupted .dist-info directory and reinstall.
Defensive patterns
Strategy: validation
Validate before calling
# Verify METADATA files are readable for installed dists before resolving.
import importlib.metadata as md, pathlib
for dist in md.distributions():
try:
_ = dist.requires_python
except FileNotFoundError:
print(f"Corrupt dist (missing METADATA): {dist.metadata['Name']}") Prevention
- Periodically validate installed dist-info directories are intact.
- Avoid manually editing/deleting files inside site-packages.
- Use pip to manage all installs/removals to keep metadata consistent.
When it happens
Trigger: Resolving a package whose .dist-info directory exists but whose METADATA file is missing, deleted, or unreadable (permission error) at the moment pip reads requires_python.
Common situations: Corrupted/partial installs; filesystem permission issues; packages whose dist-info was partially deleted; broken symlinks.
Related errors
- Invalid requirement
- Requested has inconsistent : expected , but metadata has
- Bad metadata in (invalid metadata entry 'name')
- Bad metadata in (invalid metadata entry `version`)
- Badly formatted data
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/47a343b1a614ea51.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/resolution/legacy/resolver.py:80
"""
Check whether the given Python version is compatible with a distribution's
"Requires-Python" value.
:param version_info: A 3-tuple of ints representing the Python
major-minor-micro version to check.
:param ignore_requires_python: Whether to ignore the "Requires-Python"
value if the given Python version isn't compatible.
:raises UnsupportedPythonVersion: When the given Python version isn't
compatible.
"""
# This idiosyncratically converts the SpecifierSet to str and let
# check_requires_python then parse it again into SpecifierSet. But this
# is the legacy resolver so I'm just not going to bother refactoring.
try:
requires_python = str(dist.requires_python)
except FileNotFoundError as e:
raise NoneMetadataError(dist, str(e))
try:
is_compatible = check_requires_python(
requires_python,
version_info=version_info,
)
except specifiers.InvalidSpecifier as exc:
logger.warning(
"Package %r has an invalid Requires-Python: %s", dist.raw_name, exc
)
return
if is_compatible:
return
version = ".".join(map(str, version_info))
if ignore_requires_python:
logger.debug(
"Ignoring failed Requires-Python check for package %r: %s not in %r",View on GitHub (pinned to f399c37189)