pypa/pip · error · SidecarMetadataInconsistent

Requested has inconsistent Requires-Python between its PEP…

Error message

Requested {ireq} has inconsistent Requires-Python 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:323) as SidecarMetadataInconsistent for Requires-Python. If the sidecar's Requires-Python field differs from the wheel's, pip aborts because the resolver may have chosen a wheel incompatible with the running interpreter based on stale sidecar data.

Solutions

  1. Use the official PyPI or a verified mirror.
  2. Purge local pip cache and retry.
  3. Pin a version known to be consistent for your interpreter.
  4. Report the inconsistent metadata to the index operator.

Example fix

# before
pip install pkg
# after
pip install --no-cache-dir -i https://pypi.org/simple/ 'pkg==3.1.2'
Defensive patterns

Strategy: validation

Validate before calling

from email.parser import Parser
import zipfile, io, requests

def sidecar_requires_python_matches(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 (m_w.get('Requires-Python') or '') == (m_s.get('Requires-Python') or '')

Type guard

def requires_python_match(sidecar_rp: str | None, wheel_rp: str | None) -> bool:
    return (sidecar_rp or '') == (wheel_rp or '')

Try / catch

from subprocess import run
run(["pip", "install", "--no-cache-dir", "-i", "https://pypi.org/simple/", pkg], check=True)

Prevention

When it happens

Trigger: PEP 658 sidecar Requires-Python string differs from the wheel's METADATA Requires-Python string (e.g. '>=3.8' vs '>=3.9').

Common situations: A mirror updated a wheel after a Python-version requirement bump without refreshing the sidecar; inconsistent repackaging of a wheel by a proxy/cache.

Related errors


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

Appendix: source

Thrown at src/pip/_internal/operations/prepare.py:324

            str(wheel_dist.version),
        )

    # For multi-use fields, only report the symmetric difference to avoid
    # unnecessarily flagging matching values.
    sidecar_requires = _canonical_requires(
        req, sidecar_dist, "the PEP 658 .metadata file"
    )
    wheel_requires = _canonical_requires(req, wheel_dist, "the wheel's METADATA")
    if sidecar_requires != wheel_requires:
        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:

View on GitHub (pinned to f399c37189)