pypa/pip · error · InstallationError

Project {self} uses a build backend that is missing the 'bui

Error message

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.

What it means

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.

Source

Thrown at src/pip/_internal/req/req_install.py:511

        This is done separately after pyproject.toml loading as the backend
        need to be called with the build environment's Python executable,
        which can vary."""
        self.pep517_backend = ConfiguredBuildBackendHookCaller(
            self,
            self.unpacked_source_directory,
            self._pep517_backend_spec,
            backend_path=self._pep517_backend_path,
            python_executable=python_executable,
        )

    def editable_sanity_check(self) -> None:
        """Check that an editable requirement if valid for use with PEP 517/518.

        This verifies that an editable has a build backend that supports PEP 660.
        """
        if self.editable and not self.supports_pyproject_editable:
            raise InstallationError(
                f"Project {self} uses a build backend "
                f"that is missing the 'build_editable' hook, so "
                f"it cannot be installed in editable mode. "
                f"Consider using a build backend that supports PEP 660."
            )

    def prepare_metadata(self, allow_editables: bool) -> None:
        """Ensure that project metadata is available.

        Under PEP 517 and PEP 660, call the backend hook to prepare the metadata.
        Under legacy processing, call setup.py egg-info.
        """
        assert self.source_dir, f"No source dir for {self}"
        details = self.name or f"from {self.link}"

        assert self.pep517_backend is not None
        if self.editable and allow_editables and self.supports_pyproject_editable:
            self.metadata_directory = generate_editable_metadata(

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Upgrade the build backend: require 'setuptools>=64' (and wheel) in [build-system].requires in pyproject.toml.
  2. Add/repair a pyproject.toml with a PEP 660-capable backend: build-system.backend = 'setuptools.build_meta'.
  3. If you cannot change the backend, drop '-e' and do a normal install instead.
  4. Recreate the build environment (pip cache, .egg-info, build/) so the newer backend is actually picked up.

Example fix

# before — pyproject.toml
[build-system]
requires = ["setuptools<64"]
build-backend = "setuptools.build_meta"
# pip install -e .  -> error

# after
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
Defensive patterns

Strategy: validation

Validate before calling

def backend_supports_editable(pyproject_path: str) -> bool:
    import tomllib
    with open(pyproject_path, 'rb') as f:
        data = tomllib.load(f)
    backend = data.get('build-system', {}).get('build-backend', '')
    requires = data.get('build-system', {}).get('requires', [])
    pep660_backends = {'setuptools.build_meta', 'hatchling', 'flit_core.buildapi', 'pdm.backend'}
    if backend in pep660_backends:
        return any('setuptools>=64' in r or 'hatchling' in r or 'flit' in r or 'pdm' in r for r in requires)
    return False

Type guard

def supports_pep660_editable(pyproject_path: str) -> bool:
    return backend_supports_editable(pyproject_path)

Try / catch

if editable and not supports_pep660_editable('pyproject.toml'):
    print('backend lacks build_editable; install without -e or upgrade backend')
else:
    run_pip(['install', '-e', '.'])

Prevention

When it happens

Trigger: '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.

Common situations: 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.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/86c606f7a5b52189.json. Report an issue: GitHub.