pypa/pip · error · MetadataInvalid
Requested {ireq} has invalid metadata: Requires-Dist in {sou
Error message
Requested {ireq} has invalid metadata: Requires-Dist in {source}: {e} What it means
Raised as MetadataInvalid when canonicalizing a Requires-Dist entry from a distribution's metadata fails to parse as a valid PEP 508 requirement. At prepare.py:266-273, _canonical_requires iterates raw dependency strings and calls _canonicalize_requirement, which uses get_requirement(raw.strip()); an InvalidRequirement propagates and is wrapped with the metadata source name.
Source
Thrown at src/pip/_internal/operations/prepare.py:273
def _canonical_requires(
req: InstallRequirement, dist: BaseDistribution, source: str
) -> frozenset[str]:
"""Return the canonicalized ``Requires-Dist`` entries of ``dist``.
``source`` describes which metadata file ``dist`` was parsed from, for
use in error messages.
"""
canonical: set[str] = set()
for raw in dist.iter_raw_dependencies():
try:
# strip() because a folded metadata header may be returned
# with a leading newline; iter_dependencies() strips for the
# same reason.
canonical.add(_canonicalize_requirement(raw.strip()))
except InvalidRequirement as e:
raise MetadataInvalid(req, f"Requires-Dist in {source}: {e}")
return frozenset(canonical)
def _check_sidecar_matches_wheel(
req: InstallRequirement,
sidecar_dist: BaseDistribution,
wheel_dist: BaseDistribution,
) -> None:
"""Check that a .metadata-based distribution matches the wheel's METADATA.
Compare ``Name``, ``Version``, ``Requires-Dist``, ``Requires-Python``
and ``Provides-Extra`` between the two and abort the install on any
mismatch as PEP 658 requires the metadata files "MUST be identical".
While the PEP doesn't mandate that consumers enforce the identical
requirement, it's good nonetheless to check to prevent confusing
behaviour when an index misbehaves.
View on GitHub (pinned to d7d0d0a394)
Solutions
- Open the offending *.dist-info/METADATA and review the Requires-Dist lines for syntax errors.
- Fix the requirement string to conform to PEP 508 (e.g. 'dep>=1.0; python_version<"3.12"').
- Rebuild the wheel with a current build backend and reinstall.
- Pin to a version of the package whose metadata is valid.
Example fix
# before (METADATA) Requires-Dist: numpy >=1.20, <2 # commas inside specifier are invalid in one entry # after Requires-Dist: numpy>=1.20,<2
Defensive patterns
Strategy: validation
Validate before calling
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
def validate_requires_dist(metadata_text):
for line in metadata_text.splitlines():
if line.startswith("Requires-Dist:"):
raw = line.split(":", 1)[1].strip()
try:
Requirement(raw)
except InvalidRequirement as e:
raise ValueError(f"invalid Requires-Dist {raw!r}: {e}") Type guard
from pip._vendor.packaging.requirements import Requirement, InvalidRequirement
def is_valid_requirement_str(raw: str) -> bool:
try:
Requirement(raw)
return True
except InvalidRequirement:
return False Prevention
- Lint METADATA Requires-Dist entries in CI with packaging.Requirement.
- Use a modern build backend that validates metadata on build.
- Pin to package versions known to ship valid metadata.
When it happens
Trigger: A distribution (wheel METADATA or a PEP 658 .metadata sidecar) contains a Requires-Dist line that packaging's Requirement parser rejects — e.g. malformed specifier, illegal characters, or a non-PEP-508 syntax. The 'source' in the message indicates whether it was the sidecar or the wheel METADATA.
Common situations: A package built with an old/non-compliant tool, hand-edited METADATA, a corrupted download, or a metadata field containing unsupported syntax (e.g. environment markers in an unexpected position).
Related errors
- Requested {ireq} has inconsistent Name between its PEP 658 .
- Requested {ireq} has inconsistent Name: expected {f_val!r},
- Requested {ireq} has inconsistent name: expected {f_val!r},
- Requested {ireq} has invalid metadata: {error}
- Invalid script entry point: {entry_point} - A callable suffi
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/4b26797bd9e49aad.json.
Report an issue: GitHub.