pypa/pip · error · SidecarMetadataInconsistent

Requested {ireq} has inconsistent Version between its PEP 65

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 as SidecarMetadataInconsistent for the Version field when the PEP 658 .metadata sidecar's version differs from the wheel's METADATA version. Checked at prepare.py:301-307 during _check_sidecar_matches_wheel; both values are stringified for the message.

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 d7d0d0a394)

Solutions

  1. Purge pip's cache (pip cache purge) and any HTTP cache/proxy, then reinstall.
  2. Pin to the exact version from the official index: pip install --index-url https://pypi.org/simple/ 'pkg==1.2.3'.
  3. Download the wheel directly by a verified URL/hash to skip the sidecar path.
  4. If self-hosting the index, regenerate and re-publish .metadata files whenever wheels change.

Example fix

# before
pip install pkg  # sidecar says 1.2, wheel says 1.3

# after
pip install --index-url https://pypi.org/simple/ 'pkg==1.3.0'
Defensive patterns

Strategy: fallback

Validate before calling

# compare sidecar version vs wheel METADATA version
if str(sidecar_version) != str(wheel_version):
    logger.warning("sidecar/wheel version mismatch; using direct wheel URL")

Type guard

def versions_match(a, b) -> bool:
    return str(a) == str(b)

Prevention

When it happens

Trigger: The index's .metadata sidecar advertises a different version than the wheel it accompanies. This happens when an index mirrors a wheel but keeps a stale .metadata from a prior version, or a CDN serves mismatched cached objects.

Common situations: Mirror/CDN cache desync, a private index that doesn't invalidate .metadata on wheel re-upload, or partial replication. Surfaces only for remote wheels using PEP 658 metadata.

Related errors


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