pypa/pip · error · MetadataInvalid

Requested has invalid metadata: Requires-Dist in

Error message

Requested {ireq} has invalid metadata: Requires-Dist in {source}: {e}

What it means

Raised by _canonical_requires (prepare.py:257) as a MetadataInvalid when a distribution's Requires-Dist entry cannot be parsed by packaging (InvalidRequirement). pip canonicalizes each dependency string before comparing sidecar vs wheel metadata, and any malformed PEP 508 dependency string aborts the install. It signals that the package's own metadata is broken, not that your request is wrong.

Solutions

  1. Report the broken metadata to the package maintainer — the wheel itself is invalid and cannot be installed by any PEP 508-compliant installer.
  2. Pin to an older version of the package that has valid METADATA: pip install 'pkg==<previous-working-version>'.
  3. If you control the package, fix the Requires-Dist entries in pyproject.toml/setup.cfg and rebuild the wheel.
  4. Avoid the metadata path by installing from a known-good source distribution or a different index/mirror.

Example fix

# before: installing a package with broken Requires-Dist
pip install broken-pkg
# after: pin to the last version with valid metadata
pip install 'broken-pkg==1.2.3'
Defensive patterns

Strategy: validation

Validate before calling

from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
from email.parser import Parser

def wheel_requires_dist_valid(path: str) -> bool:
    """Return True if every Requires-Dist in the wheel METADATA is PEP 508 valid."""
    import zipfile
    with zipfile.ZipFile(path) as z:
        meta = next(n for n in z.namelist() if n.endswith('.dist-info/METADATA'))
        msg = Parser().parsestr(z.read(meta).decode('utf-8', 'replace'))
    for raw in msg.get_all('Requires-Dist', []):
        try:
            Requirement(raw.strip())
        except InvalidRequirement:
            return False
    return True

Type guard

from pip._vendor.packaging.requirements import Requirement, InvalidRequirement

def is_valid_pep508_requires_dist(raw: str) -> bool:
    try:
        Requirement(raw.strip())
        return True
    except InvalidRequirement:
        return False

Try / catch

# pip is a CLI; pre-validate the candidate wheel, and on failure pin to a known-good version.
if not wheel_requires_dist_valid(whl):
    raise ValueError(f"{whl} has invalid Requires-Dist metadata; pin a known-good version")

Prevention

When it happens

Trigger: A wheel or PEP 658 .metadata file contains a Requires-Dist line that violates PEP 508 grammar (e.g. a bare URL, unparseable specifier, or stray characters). Triggered when _check_sidecar_matches_wheel iterates the raw dependencies and _canonicalize_requirement raises InvalidRequirement.

Common situations: A package was published with a hand-edited or tool-generated invalid dependency string; a typo in METADATA like 'Requires-Dist: ;;' or an unsupported marker. Also seen with very old/non-compliant packaging tools that emitted non-PEP-508 dependency text.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/4b26797bd9e49aad. Report an issue: GitHub.

Appendix: 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 f399c37189)