pypa/pip · critical · BackendUnavailable

Cannot find module {self.backend_module!r} in {self.backend_

Error message

Cannot find module {self.backend_module!r} in {self.backend_path!r}

What it means

When a backend-path is configured, pyproject_hooks installs a _BackendPathFinder that is solely responsible for locating the backend module. If PathFinder.find_spec cannot locate the module's top-level parent within backend-path, it raises BackendUnavailable('Cannot find module {backend_module!r} in {backend_path!r}'), halting the normal import machinery to guarantee the backend is loaded only from backend-path.

Source

Thrown at src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py:105

    """

    def __init__(self, backend_path, backend_module):
        self.backend_path = backend_path
        self.backend_module = backend_module
        self.backend_parent, _, _ = backend_module.partition(".")

    def find_spec(self, fullname, _path, _target=None):
        if "." in fullname:
            # Rely on importlib to find nested modules based on parent's path
            return None

        # Ignore other items in _path or sys.path and use backend_path instead:
        spec = PathFinder.find_spec(fullname, path=self.backend_path)
        if spec is None and fullname == self.backend_parent:
            # According to the spec, the backend MUST be loaded from backend-path.
            # Therefore, we can halt the import machinery and raise a clean error.
            msg = f"Cannot find module {self.backend_module!r} in {self.backend_path!r}"
            raise BackendUnavailable(msg)

        return spec

    if sys.version_info >= (3, 8):

        def find_distributions(self, context=None):
            # Delayed import: Python 3.7 does not contain importlib.metadata
            from importlib.metadata import DistributionFinder, MetadataPathFinder

            context = DistributionFinder.Context(path=self.backend_path)
            return MetadataPathFinder.find_distributions(context=context)


def _supported_features():
    """Return the list of options features supported by the backend.

    Returns a list of strings.
    The only possible value is 'build_editable'.

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Confirm the backend module file/package exists directly under a backend-path directory.
  2. Fix the build-backend module name to match the actual file/package name.
  3. Correct the backend-path entry to the directory containing the backend.
  4. Ensure the backend exposes the expected entry-point object after the ':' if one is specified.

Example fix

# before
[build-system]
build-backend = "my_backend"
backend-path = ["backend"]  # backend/my_backend.py missing

# after
[build-system]
build-backend = "my_backend"
backend-path = ["src"]  # src/my_backend.py now resolves
Defensive patterns

Strategy: validation

Validate before calling

import os
for d in backend_path_dirs:
    target = os.path.join(d, backend_module.split('.')[0])
    if not (os.path.isfile(target + '.py') or os.path.isdir(target)):
        raise FileNotFoundError(f'backend module not found under {d}')

Try / catch

try:
    backend = _build_backend()
except BackendUnavailable as e:
    if 'Cannot find module' in (e.message or ''):
        log.error('backend not in backend-path %s', e.message)
    raise

Prevention

When it happens

Trigger: pyproject.toml declares a backend-path and a build-backend whose module is not present in any of those backend-path directories; the directory exists but the expected .py file/package is missing or differently named.

Common situations: Backend source moved or renamed without updating pyproject.toml; backend-path pointing at the wrong folder; module dotted path not matching the file layout (e.g. backend='my_backend' but file is my_backend/__init__.py missing).

Related errors


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