{"record":{"id":"4b26797bd9e49aad","repo":"pypa/pip","slug":"requested-ireq-has-invalid-metadata-requires-di","errorCode":null,"errorMessage":"Requested {ireq} has invalid metadata: Requires-Dist in {source}: {e}","messagePattern":"Requested (.+?) has invalid metadata: Requires-Dist in (.+?): (.+?)","errorType":"exception","errorClass":"MetadataInvalid","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/operations/prepare.py","lineNumber":273,"sourceCode":"\n\ndef _canonical_requires(\n    req: InstallRequirement, dist: BaseDistribution, source: str\n) -> frozenset[str]:\n    \"\"\"Return the canonicalized ``Requires-Dist`` entries of ``dist``.\n\n    ``source`` describes which metadata file ``dist`` was parsed from, for\n    use in error messages.\n    \"\"\"\n    canonical: set[str] = set()\n    for raw in dist.iter_raw_dependencies():\n        try:\n            # strip() because a folded metadata header may be returned\n            # with a leading newline; iter_dependencies() strips for the\n            # same reason.\n            canonical.add(_canonicalize_requirement(raw.strip()))\n        except InvalidRequirement as e:\n            raise MetadataInvalid(req, f\"Requires-Dist in {source}: {e}\")\n    return frozenset(canonical)\n\n\ndef _check_sidecar_matches_wheel(\n    req: InstallRequirement,\n    sidecar_dist: BaseDistribution,\n    wheel_dist: BaseDistribution,\n) -> None:\n    \"\"\"Check that a .metadata-based distribution matches the wheel's METADATA.\n\n    Compare ``Name``, ``Version``, ``Requires-Dist``, ``Requires-Python``\n    and ``Provides-Extra`` between the two and abort the install on any\n    mismatch as PEP 658 requires the metadata files \"MUST be identical\".\n\n    While the PEP doesn't mandate that consumers enforce the identical\n    requirement, it's good nonetheless to check to prevent confusing\n    behaviour when an index misbehaves.\n","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/operations/prepare.py#L255-L291","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Report the broken metadata to the package maintainer — the wheel itself is invalid and cannot be installed by any PEP 508-compliant installer.","Pin to an older version of the package that has valid METADATA: pip install 'pkg==<previous-working-version>'.","If you control the package, fix the Requires-Dist entries in pyproject.toml/setup.cfg and rebuild the wheel.","Avoid the metadata path by installing from a known-good source distribution or a different index/mirror."],"exampleFix":"# before: installing a package with broken Requires-Dist\npip install broken-pkg\n# after: pin to the last version with valid metadata\npip install 'broken-pkg==1.2.3'","handlingStrategy":"validation","validationCode":"from pip._vendor.packaging.requirements import InvalidRequirement, Requirement\nfrom email.parser import Parser\n\ndef wheel_requires_dist_valid(path: str) -> bool:\n    \"\"\"Return True if every Requires-Dist in the wheel METADATA is PEP 508 valid.\"\"\"\n    import zipfile\n    with zipfile.ZipFile(path) as z:\n        meta = next(n for n in z.namelist() if n.endswith('.dist-info/METADATA'))\n        msg = Parser().parsestr(z.read(meta).decode('utf-8', 'replace'))\n    for raw in msg.get_all('Requires-Dist', []):\n        try:\n            Requirement(raw.strip())\n        except InvalidRequirement:\n            return False\n    return True","typeGuard":"from pip._vendor.packaging.requirements import Requirement, InvalidRequirement\n\ndef is_valid_pep508_requires_dist(raw: str) -> bool:\n    try:\n        Requirement(raw.strip())\n        return True\n    except InvalidRequirement:\n        return False","tryCatchPattern":"# pip is a CLI; pre-validate the candidate wheel, and on failure pin to a known-good version.\nif not wheel_requires_dist_valid(whl):\n    raise ValueError(f\"{whl} has invalid Requires-Dist metadata; pin a known-good version\")","preventionTips":["When publishing, validate METADATA Requires-Dist with packaging.requirements before uploading.","Pin packages to versions you have validated.","Run 'twine check' on built distributions before release."],"tags":["metadata","pep508","requires-dist","validation","pip"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}