{"id":"c35284f9f6a6b972","repo":"pypa/pip","slug":"dist-info-directory-not-found","errorCode":null,"errorMessage":".dist-info directory not found","messagePattern":"\\.dist-info directory not found","errorType":"exception","errorClass":"UnsupportedWheel","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/utils/wheel.py","lineNumber":48,"sourceCode":"\n    check_compatibility(version, name)\n\n    return info_dir, metadata\n\n\ndef wheel_dist_info_dir(source: ZipFile, name: str) -> str:\n    \"\"\"Returns the name of the contained .dist-info directory.\n\n    Raises AssertionError or UnsupportedWheel if not found, >1 found, or\n    it doesn't match the provided name.\n    \"\"\"\n    # Zip file path separators must be /\n    subdirs = {p.split(\"/\", 1)[0] for p in source.namelist()}\n\n    info_dirs = [s for s in subdirs if s.endswith(\".dist-info\")]\n\n    if not info_dirs:\n        raise UnsupportedWheel(\".dist-info directory not found\")\n\n    if len(info_dirs) > 1:\n        raise UnsupportedWheel(\n            \"multiple .dist-info directories found: {}\".format(\", \".join(info_dirs))\n        )\n\n    info_dir = info_dirs[0]\n\n    info_dir_name = canonicalize_name(info_dir)\n    canonical_name = canonicalize_name(name)\n    if not info_dir_name.startswith(canonical_name):\n        raise UnsupportedWheel(\n            f\".dist-info directory {info_dir!r} does not start with {canonical_name!r}\"\n        )\n\n    return info_dir\n\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/utils/wheel.py#L30-L66","documentation":"UnsupportedWheel raised by wheel_dist_info_dir when no top-level directory ending in `.dist-info` exists in the wheel zip. A valid wheel must contain exactly one `<name>-<version>.dist-info` directory holding its metadata. Absence means the archive is structurally not a wheel.","triggerScenarios":"parse_wheel on a zip that has no .dist-info subdir at all. Occurs with renamed plain zips, with wheels whose build backend forgot to emit metadata, or with corrupted/partial wheels.","commonSituations":"Building a wheel manually without metadata; zip truncated mid-write; .whl extension on a plain archive; third-party packaging tool that omits metadata.","solutions":["Inspect: `unzip -l pkg.whl | grep dist-info` — confirm presence.","Rebuild with a standard backend (setuptools/hatchling/flit) which always emits .dist-info.","Re-download from a trusted index and verify hash.","Run `twine check` on the artifact before publishing/installing."],"exampleFix":"// before\n# manual zip without metadata\nzip -r pkg.whl pkg_module/\n\n// after\n# use a real backend so .dist-info is emitted:\npython -m build --wheel","handlingStrategy":"validation","validationCode":"import zipfile\ndef has_dist_info(path: str) -> bool:\n    with zipfile.ZipFile(path) as z:\n        return any(n.split('/',1)[0].endswith('.dist-info') for n in z.namelist())","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Build wheels with a PEP 517 backend.","Inspect with `unzip -l pkg.whl` before install.","Run `twine check`.","Verify hashes from the index."],"tags":["pip","wheel","metadata","dist-info"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}