pypa/pip · error · SidecarMetadataInconsistent
Requested has inconsistent Provides-Extra between its PEP…
Error message
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} What it means
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.
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.
Example fix
# before pip install 'pkg[missing-extra]' # after: use consistent upstream pip install --no-cache-dir -i https://pypi.org/simple/ 'pkg[valid-extra]==1.0.0'
Defensive patterns
Strategy: validation
Validate before calling
from email.parser import Parser
import zipfile, io, requests
def _extras_set(msg):
return frozenset(msg.get_all('Provides-Extra', []))
def sidecar_extras_match(wheel_url: str, sidecar_url: str) -> bool:
wb = requests.get(wheel_url).content
zf = zipfile.ZipFile(io.BytesIO(wb))
m_w = Parser().parsestr(zf.read(next(n for n in zf.namelist() if n.endswith('.dist-info/METADATA'))).decode())
m_s = Parser().parsestr(requests.get(sidecar_url).text)
return _extras_set(m_w) == _extras_set(m_s) Type guard
def extras_match(sidecar_extras: list[str], wheel_extras: list[str]) -> bool:
return frozenset(sidecar_extras) == frozenset(wheel_extras) Try / catch
from subprocess import run run(["pip", "install", "--no-cache-dir", "-i", "https://pypi.org/simple/", pkg], check=True)
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: A wheel re-upload added/removed an extra but the mirror's sidecar was not regenerated; index software that drops or reorders extras inconsistently.
Related errors
- Requested has inconsistent Name between its PEP 658…
- Requested has inconsistent Requires-Dist between its PEP…
- Requested has inconsistent Requires-Python between its PEP…
- Requested has inconsistent Version between its PEP 658…
- Requested has inconsistent Name: expected , but metadata has
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/496ea7c631c8992e.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/operations/prepare.py:334
raise SidecarMetadataInconsistent(
req,
"Requires-Dist",
", ".join(sorted(sidecar_requires - wheel_requires)),
", ".join(sorted(wheel_requires - sidecar_requires)),
)
if sidecar_dist.requires_python != wheel_dist.requires_python:
raise SidecarMetadataInconsistent(
req,
"Requires-Python",
str(sidecar_dist.requires_python),
str(wheel_dist.requires_python),
)
sidecar_extras = frozenset(sidecar_dist.iter_provided_extras())
wheel_extras = frozenset(wheel_dist.iter_provided_extras())
if sidecar_extras != wheel_extras:
raise SidecarMetadataInconsistent(
req,
"Provides-Extra",
", ".join(sorted(sidecar_extras - wheel_extras)),
", ".join(sorted(wheel_extras - sidecar_extras)),
)
class RequirementPreparer:
"""Prepares a Requirement"""
def __init__(
self,
*,
build_dir: str,
download_dir: str | None,
src_dir: str,
build_isolation: BuildIsolationMode,
build_isolation_installer: BuildEnvironmentInstaller,View on GitHub (pinned to f399c37189)