pypa/pip · error · MissingPyProjectBuildRequires

missing-pyproject-build-system-requires

missing-pyproject-build-system-requires

Error message

Can not process {package}

What it means

Raised by load_pyproject_toml (pyproject.py:84) as MissingPyProjectBuildRequires (code: missing-pyproject-build-system-requires) when a pyproject.toml has a [build-system] table but that table lacks the required 'requires' key. PEP 518 mandates that [build-system] must contain 'requires', so pip refuses to build.

Solutions

  1. Add the 'requires' array to [build-system] listing build dependencies (e.g. setuptools + wheel).
  2. Remove the [build-system] table entirely so pip applies the setuptools legacy defaults.
  3. Validate the pyproject.toml with a linter/schema checker before publishing.

Example fix

# before (pyproject.toml)
[build-system]
build-backend = "setuptools.build_meta"
# after
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
Defensive patterns

Strategy: validation

Validate before calling

from pip._internal.utils.compat import tomllib

def build_system_has_requires(pyproject_path: str) -> tuple[bool, str | None]:
    with open(pyproject_path, 'rb') as f:
        data = tomllib.load(f)
    bs = data.get('build-system')
    if bs is not None and 'requires' not in bs:
        return False, '[build-system] present but missing "requires"'
    return True, None

Type guard

from typing import Any

def has_build_requires(build_system: dict[str, Any] | None) -> bool:
    return build_system is None or isinstance(build_system.get('requires'), list)

Try / catch

from subprocess import run, CalledProcessError
try:
    run(["pip", "install", target], check=True)
except CalledProcessError:
    # Add the requires array to [build-system] then rebuild.
    run(["python", "-m", "build", target], check=True)

Prevention

When it happens

Trigger: A pyproject.toml containing '[build-system]' with only 'build-backend' (or 'backend-path') and no 'requires' array. The check 'if "requires" not in build_system' fires.

Common situations: Hand-authored pyproject.toml where the author listed a backend but forgot the requires; migration artifacts where build-system was partially populated; tooling that writes backend-path without requires.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/e53ec9e9c7836b89. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_internal/pyproject.py:85

        build_system = None

    if build_system is None:
        # In the absence of any explicit backend specification, we
        # assume the setuptools backend that most closely emulates the
        # traditional direct setup.py execution, and require wheel and
        # a version of setuptools that supports that backend.

        build_system = {
            "requires": ["setuptools>=40.8.0"],
            "build-backend": "setuptools.build_meta:__legacy__",
        }

    # Ensure that the build-system section in pyproject.toml conforms
    # to PEP 518.

    # Specifying the build-system table but not the requires key is invalid
    if "requires" not in build_system:
        raise MissingPyProjectBuildRequires(package=req_name)

    # Error out if requires is not a list of strings
    requires = build_system["requires"]
    if not _is_list_of_str(requires):
        raise InvalidPyProjectBuildRequires(
            package=req_name,
            reason="It is not a list of strings.",
        )

    # Each requirement must be valid as per PEP 508
    for requirement in requires:
        try:
            get_requirement(requirement)
        except InvalidRequirement as error:
            raise InvalidPyProjectBuildRequires(
                package=req_name,
                reason=f"It contains an invalid requirement: {requirement!r}",
            ) from error

View on GitHub (pinned to f399c37189)