pypa/pip · error · SidecarMetadataInconsistent

Requested has inconsistent Version between its PEP 658…

Error message

Requested {ireq} has inconsistent Version 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:301) as SidecarMetadataInconsistent for the Version field. The PEP 658 sidecar's version must equal the wheel's version; a divergence means the resolver planned against one version while a different one would be installed. pip rejects this defensively per the PEP's 'MUST be identical' requirement.

Solutions

  1. Use a different/more-up-to-date index or the official PyPI.
  2. Purge the local pip cache and retry.
  3. Contact the index maintainer to regenerate the PEP 658 sidecar metadata.
  4. Pin the exact version explicitly so pip resolves the correct wheel.

Example fix

# before
pip install pkg
# after
pip install --no-cache-dir 'pkg==2.0.1'
pip cache purge
Defensive patterns

Strategy: validation

Validate before calling

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

def sidecar_version_matches(wheel_url: str, sidecar_url: str) -> bool:
    wb = requests.get(wheel_url).content
    zf = zipfile.ZipFile(io.BytesIO(wb))
    meta = zf.read(next(n for n in zf.namelist() if n.endswith('.dist-info/METADATA'))).decode()
    v_w = Parser().parsestr(meta)['Version']
    v_s = Parser().parsestr(requests.get(sidecar_url).text)['Version']
    return v_s == v_w

Type guard

def versions_match(sidecar_version: str, wheel_version: str) -> bool:
    return str(sidecar_version) == str(wheel_version)

Try / catch

# Pin an exact version and use a trusted index to bypass mirror inconsistency.
from subprocess import run
run(["pip", "install", "--no-cache-dir", "-i", "https://pypi.org/simple/", f"{pkg}=={ver}"], check=True)

Prevention

When it happens

Trigger: The downloaded PEP 658 .metadata sidecar advertises a different version than the wheel's METADATA Version field. Comparison is done on sidecar_dist.version vs wheel_dist.version.

Common situations: A mirror partially updated a package (new wheel, old sidecar) or vice-versa; a re-upload of the same filename with different contents on an index that does not invalidate the sidecar cache; race conditions on a custom artifact server.

Related errors


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

Appendix: source

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

    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.

    Also note for name and version, pip usually rejects wheels if they're
    inconsistent already. Checking them again here is purely defensive.
    """

    sidecar_name = canonicalize_name(sidecar_dist.raw_name)
    wheel_name = canonicalize_name(wheel_dist.raw_name)
    if sidecar_name != wheel_name:
        raise SidecarMetadataInconsistent(req, "Name", sidecar_name, wheel_name)

    if sidecar_dist.version != wheel_dist.version:
        raise SidecarMetadataInconsistent(
            req,
            "Version",
            str(sidecar_dist.version),
            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)),

View on GitHub (pinned to f399c37189)