{"record":{"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/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/req/req_install.py#L493-L529","documentation":"editable_sanity_check (req_install.py:511) verifies that a project being installed in editable mode (-e) uses a build backend implementing PEP 660's build_editable hook. Legacy backends or old setuptools versions lack this hook, so pip cannot produce an editable install and raises InstallationError instead of silently failing.","triggerScenarios":"Running `pip install -e .` on a project whose build backend (declared in pyproject.toml [build-system] or falling back to setup.py legacy) does not expose build_editable.","commonSituations":"Very old setuptools (<64); a custom/legacy build backend without PEP 660 support; project with only a setup.py and no pyproject.toml on an old setuptools.","solutions":["Upgrade build tooling: pip install -U setuptools wheel (setuptools >=64 supports PEP 660).","Ensure pyproject.toml declares a PEP 660-capable backend under [build-system].","Install non-editable (pip install .) as a workaround until the backend is upgraded."],"exampleFix":"# before\npip install -e .\n# after\npip install -U setuptools>=64 wheel && pip install -e .","handlingStrategy":"validation","validationCode":"# Before pip install -e ., verify the backend exposes build_editable.\nimport tomllib, pathlib, subprocess, sys, json\npyproject = pathlib.Path(\"pyproject.toml\")\nif pyproject.exists():\n    data = tomllib.loads(pyproject.read_text())\n    bs = data.get(\"build-system\", {})\n    backend = bs.get(\"build-backend\", \"setuptools.build_meta\")\n    # ensure setuptools is new enough (>=64 has PEP 660)\n    import importlib.metadata as md\n    stv = md.version(\"setuptools\")\n    if tuple(map(int, stv.split(\".\")[:2])) < (6, 4) and \"setuptools\" in backend:\n        subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-U\", \"setuptools>=64\"])","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep setuptools >= 64 in any environment used for editable installs.","Declare a PEP 660-capable backend in pyproject.toml.","CI: pin a modern setuptools in your build requirements."],"tags":["editable","pep660","build-backend"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}