{"record":{"id":"496ea7c631c8992e","repo":"pypa/pip","slug":"requested-ireq-has-inconsistent-provides-extra-b","errorCode":null,"errorMessage":"Requested {ireq} has inconsistent Provides-Extra between its PEP 658 .metadata file and the wheel's METADATA: sidecar has {f_val!r}, wheel has {m_val!r}","messagePattern":"Requested (.+?) has inconsistent Provides-Extra between its PEP 658 \\.metadata file and the wheel's METADATA: sidecar has (.+?), wheel has (.+?)","errorType":"exception","errorClass":"SidecarMetadataInconsistent","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/operations/prepare.py","lineNumber":334,"sourceCode":"        raise SidecarMetadataInconsistent(\n            req,\n            \"Requires-Dist\",\n            \", \".join(sorted(sidecar_requires - wheel_requires)),\n            \", \".join(sorted(wheel_requires - sidecar_requires)),\n        )\n\n    if sidecar_dist.requires_python != wheel_dist.requires_python:\n        raise SidecarMetadataInconsistent(\n            req,\n            \"Requires-Python\",\n            str(sidecar_dist.requires_python),\n            str(wheel_dist.requires_python),\n        )\n\n    sidecar_extras = frozenset(sidecar_dist.iter_provided_extras())\n    wheel_extras = frozenset(wheel_dist.iter_provided_extras())\n    if sidecar_extras != wheel_extras:\n        raise SidecarMetadataInconsistent(\n            req,\n            \"Provides-Extra\",\n            \", \".join(sorted(sidecar_extras - wheel_extras)),\n            \", \".join(sorted(wheel_extras - sidecar_extras)),\n        )\n\n\nclass RequirementPreparer:\n    \"\"\"Prepares a Requirement\"\"\"\n\n    def __init__(\n        self,\n        *,\n        build_dir: str,\n        download_dir: str | None,\n        src_dir: str,\n        build_isolation: BuildIsolationMode,\n        build_isolation_installer: BuildEnvironmentInstaller,","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/operations/prepare.py#L316-L352","documentation":"Raised by _check_sidecar_matches_wheel (prepare.py:333) as SidecarMetadataInconsistent for Provides-Extra. pip compares the set of extras advertised in the sidecar vs the wheel; if they differ it reports the extras only present in each and aborts, because a resolver might offer extras that the wheel cannot actually satisfy.","triggerScenarios":"The frozenset of extras from iter_provided_extras() on the sidecar differs from the wheel's. Message shows sidecar-only vs wheel-only extra names.","commonSituations":"A wheel re-upload added/removed an extra but the mirror's sidecar was not regenerated; index software that drops or reorders extras inconsistently.","solutions":["Verify against the official PyPI or a fresh mirror.","Clear the local cache and re-download.","Avoid requesting the missing/extra extra explicitly, or pin a consistent version.","Notify the index operator to fix the sidecar."],"exampleFix":"# before\npip install 'pkg[missing-extra]'\n# after: use consistent upstream\npip install --no-cache-dir -i https://pypi.org/simple/ 'pkg[valid-extra]==1.0.0'","handlingStrategy":"validation","validationCode":"from email.parser import Parser\nimport zipfile, io, requests\n\ndef _extras_set(msg):\n    return frozenset(msg.get_all('Provides-Extra', []))\n\ndef sidecar_extras_match(wheel_url: str, sidecar_url: str) -> bool:\n    wb = requests.get(wheel_url).content\n    zf = zipfile.ZipFile(io.BytesIO(wb))\n    m_w = Parser().parsestr(zf.read(next(n for n in zf.namelist() if n.endswith('.dist-info/METADATA'))).decode())\n    m_s = Parser().parsestr(requests.get(sidecar_url).text)\n    return _extras_set(m_w) == _extras_set(m_s)","typeGuard":"def extras_match(sidecar_extras: list[str], wheel_extras: list[str]) -> bool:\n    return frozenset(sidecar_extras) == frozenset(wheel_extras)","tryCatchPattern":"from subprocess import run\nrun([\"pip\", \"install\", \"--no-cache-dir\", \"-i\", \"https://pypi.org/simple/\", pkg], check=True)","preventionTips":["Verify extras against the wheel before relying on a mirror's sidecar.","Use trusted indexes for reproducible installs.","Mirror operators: regenerate sidecars whenever extras change."],"tags":["pep658","metadata","sidecar","provides-extra","index","pip"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}