pypa/pip · error · UnsupportedWheel

multiple .dist-info directories found

Error message

multiple .dist-info directories found: {}

What it means

Raised by wheel_dist_info_dir() when the wheel zip contains more than one top-level '.dist-info' directory. A valid wheel must contain exactly one .dist-info directory; multiple indicate a malformed or merged archive.

Solutions

  1. List the wheel contents: 'unzip -l <file>.whl' and identify the multiple .dist-info entries
  2. Rebuild the wheel cleanly from source with 'python -m build --wheel'
  3. Re-download the wheel from the official PyPI index
  4. If you control the build, ensure only one distribution's metadata is emitted per wheel

Example fix

// before
pip install ./merged-1.0-py3-none-any.whl  # contains two .dist-info dirs
// after
# rebuild a single clean wheel
python -m build --wheel --no-isolation
pip install dist/merged-1.0-py3-none-any.whl
Defensive patterns

Strategy: validation

Validate before calling

import zipfile

def wheel_has_single_dist_info(path: str) -> bool:
    with zipfile.ZipFile(path) as zf:
        dirs = {n.split('/')[0] for n in zf.namelist() if '/' in n}
        return sum(1 for d in dirs if d.endswith('.dist-info')) == 1

Type guard

import zipfile

def has_exactly_one_dist_info(zf: zipfile.ZipFile) -> bool:
    dirs = {n.split('/')[0] for n in zf.namelist() if '/' in n}
    return sum(1 for d in dirs if d.endswith('.dist-info')) == 1

Try / catch

from pip._internal.exceptions import UnsupportedWheel

try:
    wheel_dist_info_dir(wheel_zip, name)
except UnsupportedWheel as e:
    if 'multiple .dist-info' in str(e):
        raise PackagingError(f'wheel contains multiple distributions: {e}')
    raise

Prevention

When it happens

Trigger: Calling wheel_dist_info_dir(source, name) where the set of top-level namelist entries contains two or more names ending in '.dist-info'. Reached during any wheel installation via parse_wheel().

Common situations: Two wheels manually zipped together. A build tool bug that emits metadata for multiple distributions into one wheel. A wheel repackaging tool that concatenated archives. A corrupted index serving a merged artifact.

Related errors


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

Appendix: source

Thrown at src/pip/_internal/utils/wheel.py:51

    return info_dir, metadata


def wheel_dist_info_dir(source: ZipFile, name: str) -> str:
    """Returns the name of the contained .dist-info directory.

    Raises AssertionError or UnsupportedWheel if not found, >1 found, or
    it doesn't match the provided name.
    """
    # Zip file path separators must be /
    subdirs = {p.split("/", 1)[0] for p in source.namelist()}

    info_dirs = [s for s in subdirs if s.endswith(".dist-info")]

    if not info_dirs:
        raise UnsupportedWheel(".dist-info directory not found")

    if len(info_dirs) > 1:
        raise UnsupportedWheel(
            "multiple .dist-info directories found: {}".format(", ".join(info_dirs))
        )

    info_dir = info_dirs[0]

    info_dir_name = canonicalize_name(info_dir)
    canonical_name = canonicalize_name(name)
    if not info_dir_name.startswith(canonical_name):
        raise UnsupportedWheel(
            f".dist-info directory {info_dir!r} does not start with {canonical_name!r}"
        )

    return info_dir


def read_wheel_metadata_file(source: ZipFile, path: str) -> bytes:
    try:
        return source.read(path)

View on GitHub (pinned to f399c37189)