{"id":"e73217d194620540","repo":"pypa/pip","slug":"no-dist-info-folder-found-in-wheel","errorCode":null,"errorMessage":"No .dist-info folder found in wheel","messagePattern":"No \\.dist-info folder found in wheel","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py","lineNumber":224,"sourceCode":"                whl_basename, metadata_directory, config_settings\n            )\n    else:\n        return hook(metadata_directory, config_settings)\n\n\nWHEEL_BUILT_MARKER = \"PYPROJECT_HOOKS_ALREADY_BUILT_WHEEL\"\n\n\ndef _dist_info_files(whl_zip):\n    \"\"\"Identify the .dist-info folder inside a wheel ZipFile.\"\"\"\n    res = []\n    for path in whl_zip.namelist():\n        m = re.match(r\"[^/\\\\]+-[^/\\\\]+\\.dist-info/\", path)\n        if m:\n            res.append(path)\n    if res:\n        return res\n    raise Exception(\"No .dist-info folder found in wheel\")\n\n\ndef _get_wheel_metadata_from_wheel(whl_basename, metadata_directory, config_settings):\n    \"\"\"Extract the metadata from a wheel.\n\n    Fallback for when the build backend does not\n    define the 'get_wheel_metadata' hook.\n    \"\"\"\n    from zipfile import ZipFile\n\n    with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), \"wb\"):\n        pass  # Touch marker file\n\n    whl_file = os.path.join(metadata_directory, whl_basename)\n    with ZipFile(whl_file) as zipf:\n        dist_info = _dist_info_files(zipf)\n        zipf.extractall(path=metadata_directory, members=dist_info)\n    return dist_info[0].split(\"/\")[0]","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py#L206-L242","documentation":"When pyproject_hooks falls back to extracting metadata from a built wheel (_get_wheel_metadata_from_wheel), _dist_info_files scans the wheel zip for a '<name>-<version>.dist-info/' folder. If none is found it raises a bare Exception('No .dist-info folder found in wheel'), indicating the produced wheel is malformed.","triggerScenarios":"prepare_metadata_for_build_wheel is unsupported by the backend, so a wheel is built and its .dist-info extracted; the backend produced a wheel with no dist-info directory (violating the wheel spec). Also reachable if the wheel file is corrupt or truncated so the zip listing omits the folder.","commonSituations":"A buggy or non-compliant build backend that omits dist-info; a wheel assembled by hand or a custom backend that forgets METADATA; filesystem/zip corruption during the build.","solutions":["Report/fix the backend so its built wheel includes a proper <name>-<version>.dist-info directory with METADATA.","Upgrade or switch to a spec-compliant backend (setuptools, hatchling, flit).","Rebuild cleanly to rule out a corrupt intermediate wheel; clear any build cache."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import zipfile, re\nwith zipfile.ZipFile(wheel_path) as z:\n    if not any(re.match(r'[^/\\\\]+-[^/\\\\]+\\.dist-info/', n) for n in z.namelist()):\n        raise ValueError('wheel is missing a .dist-info folder')","typeGuard":null,"tryCatchPattern":"try:\n    meta = _get_wheel_metadata_from_wheel(basename, md_dir, cfg)\nexcept Exception as e:\n    if 'No .dist-info' in str(e):\n        log.error('backend produced a non-compliant wheel: %s', e)\n    raise","preventionTips":["Use a spec-compliant backend that emits dist-info.","Validate built wheels with 'python -m zipfile -l' before relying on them."],"tags":["pyproject-hooks","wheel","metadata","build"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}