{"id":"86c606f7a5b52189","repo":"pypa/pip","slug":"project-self-uses-a-build-backend-that-is-missin","errorCode":null,"errorMessage":"Project {self} uses a build backend that is missing the 'build_editable' hook, so it cannot be installed in editable mode. Consider using a build backend that supports PEP 660.","messagePattern":"Project (.+?) uses a build backend that is missing the 'build_editable' hook, so it cannot be installed in editable mode\\. Consider using a build backend that supports PEP 660\\.","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/req/req_install.py","lineNumber":511,"sourceCode":"\n        This is done separately after pyproject.toml loading as the backend\n        need to be called with the build environment's Python executable,\n        which can vary.\"\"\"\n        self.pep517_backend = ConfiguredBuildBackendHookCaller(\n            self,\n            self.unpacked_source_directory,\n            self._pep517_backend_spec,\n            backend_path=self._pep517_backend_path,\n            python_executable=python_executable,\n        )\n\n    def editable_sanity_check(self) -> None:\n        \"\"\"Check that an editable requirement if valid for use with PEP 517/518.\n\n        This verifies that an editable has a build backend that supports PEP 660.\n        \"\"\"\n        if self.editable and not self.supports_pyproject_editable:\n            raise InstallationError(\n                f\"Project {self} uses a build backend \"\n                f\"that is missing the 'build_editable' hook, so \"\n                f\"it cannot be installed in editable mode. \"\n                f\"Consider using a build backend that supports PEP 660.\"\n            )\n\n    def prepare_metadata(self, allow_editables: bool) -> None:\n        \"\"\"Ensure that project metadata is available.\n\n        Under PEP 517 and PEP 660, call the backend hook to prepare the metadata.\n        Under legacy processing, call setup.py egg-info.\n        \"\"\"\n        assert self.source_dir, f\"No source dir for {self}\"\n        details = self.name or f\"from {self.link}\"\n\n        assert self.pep517_backend is not None\n        if self.editable and allow_editables and self.supports_pyproject_editable:\n            self.metadata_directory = generate_editable_metadata(","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/req/req_install.py#L493-L529","documentation":"InstallationError from InstallRequirement.editable_sanity_check: the requirement is editable (-e) but the project's PEP 517 build backend does not expose the 'build_editable' hook defined by PEP 660. pip detects this via supports_pyproject_editable and aborts before trying to call a hook that does not exist, pointing the user at PEP 660.","triggerScenarios":"'pip install -e .' (or '-e <vcs url>') for a project whose pyproject.toml declares a build-system.backend (e.g. an old setuptools, a custom backend, or a bare legacy setup.py with no PEP 660 support) lacking the build_editable hook.","commonSituations":"Old setuptools (<64) in the build environment; a project that only ships setup.py and a minimal/no pyproject.toml; a custom backend that implemented build_wheel but never build_editable; pinning 'setuptools<64' in build-system.requires.","solutions":["Upgrade the build backend: require 'setuptools>=64' (and wheel) in [build-system].requires in pyproject.toml.","Add/repair a pyproject.toml with a PEP 660-capable backend: build-system.backend = 'setuptools.build_meta'.","If you cannot change the backend, drop '-e' and do a normal install instead.","Recreate the build environment (pip cache, .egg-info, build/) so the newer backend is actually picked up."],"exampleFix":"# before — pyproject.toml\n[build-system]\nrequires = [\"setuptools<64\"]\nbuild-backend = \"setuptools.build_meta\"\n# pip install -e .  -> error\n\n# after\n[build-system]\nrequires = [\"setuptools>=64\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"","handlingStrategy":"validation","validationCode":"def backend_supports_editable(pyproject_path: str) -> bool:\n    import tomllib\n    with open(pyproject_path, 'rb') as f:\n        data = tomllib.load(f)\n    backend = data.get('build-system', {}).get('build-backend', '')\n    requires = data.get('build-system', {}).get('requires', [])\n    pep660_backends = {'setuptools.build_meta', 'hatchling', 'flit_core.buildapi', 'pdm.backend'}\n    if backend in pep660_backends:\n        return any('setuptools>=64' in r or 'hatchling' in r or 'flit' in r or 'pdm' in r for r in requires)\n    return False","typeGuard":"def supports_pep660_editable(pyproject_path: str) -> bool:\n    return backend_supports_editable(pyproject_path)","tryCatchPattern":"if editable and not supports_pep660_editable('pyproject.toml'):\n    print('backend lacks build_editable; install without -e or upgrade backend')\nelse:\n    run_pip(['install', '-e', '.'])","preventionTips":["Pin 'setuptools>=64' in [build-system].requires for editable installs.","Add a CI job that runs 'pip install -e .' to catch missing build_editable early.","Keep a modern pyproject.toml with an explicit build-backend."],"tags":["editable","pep517","pep660","build-backend","setuptools"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}