{"id":"244703032101a24e","repo":"pypa/pip","slug":"build-editable","errorCode":null,"errorMessage":"build_editable","messagePattern":"build_editable","errorType":"exception","errorClass":"HookMissing","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py","lineNumber":202,"sourceCode":"def prepare_metadata_for_build_editable(\n    metadata_directory, config_settings, _allow_fallback\n):\n    \"\"\"Invoke optional prepare_metadata_for_build_editable\n\n    Implements a fallback by building an editable wheel if the hook isn't\n    defined, unless _allow_fallback is False in which case HookMissing is\n    raised.\n    \"\"\"\n    backend = _build_backend()\n    try:\n        hook = backend.prepare_metadata_for_build_editable\n    except AttributeError:\n        if not _allow_fallback:\n            raise HookMissing()\n        try:\n            build_hook = backend.build_editable\n        except AttributeError:\n            raise HookMissing(hook_name=\"build_editable\")\n        else:\n            whl_basename = build_hook(metadata_directory, config_settings)\n            return _get_wheel_metadata_from_wheel(\n                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:","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py#L184-L220","documentation":"During prepare_metadata_for_build_editable's fallback path, if the backend lacks prepare_metadata_for_build_editable AND also lacks build_editable, pyproject_hooks raises HookMissing(hook_name='build_editable'). The message is just the hook name 'build_editable', signaling the backend does not support editable installs.","triggerScenarios":"A build backend that predates PEP 660 editable support is asked to produce editable metadata (e.g. pip install -e on a project whose backend defines neither prepare_metadata_for_build_editable nor build_editable).","commonSituations":"Using an older setuptools (<64) or a minimal custom backend with `pip install -e .`; tooling (pip, build) probing editable support via _supported_features and then attempting the editable hook.","solutions":["Upgrade the build backend to a version that supports PEP 660 editable installs (e.g. setuptools>=64, hatchling, flit_core>=3.6).","If editable install is optional, fall back to a regular install (pip install .) for that project.","For a custom backend, implement build_editable (and optionally prepare_metadata_for_build_editable)."],"exampleFix":"# before\nrequires = [\"setuptools==63\"]\n# running: pip install -e .\n\n# after\nrequires = [\"setuptools>=64\"]\n# editable install now supported","handlingStrategy":"validation","validationCode":"features = hook._supported_features()\nif 'build_editable' not in features:\n    raise RuntimeError('backend does not support editable installs (PEP 660)')","typeGuard":null,"tryCatchPattern":"from pip._vendor.pyproject_hooks._impl import HookMissing\ntry:\n    hook.prepare_metadata_for_build_editable(md_dir)\nexcept HookMissing as e:\n    if e.hook_name == 'build_editable':\n        log.warning('editable not supported; doing a regular install')","preventionTips":["Check _supported_features() for 'build_editable' before attempting -e installs.","Keep the backend version current for PEP 660 support."],"tags":["pyproject-hooks","pep660","editable-install","build"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}