pypa/pip · error · InstallWheelBuildError

failed-wheel-build-for-install

failed-wheel-build-for-install

Error message

Failed to build installable wheels for some pyproject.toml based projects

What it means

Raised by `pip install` when one or more packages failed to build a wheel from source (pyproject.toml-based projects). InstallCommand.run at install.py:523 calls build() over reqs_to_build; if build_failures is non-empty it raises InstallWheelBuildError (a DiagnosticPipError with code 'failed-wheel-build-for-install'). The underlying causes are captured in build_failures and detailed in pip's preceding output.

Solutions

  1. Read the full build output above this error — it names the failing package and the real build error (e.g. missing compiler, missing header).
  2. Install build prerequisites: compiler toolchain, python-dev headers, and the package's documented system deps.
  3. Upgrade pip, setuptools, and wheel: `python -m pip install --upgrade pip setuptools wheel`.
  4. Do not disable build isolation (--no-build-isolation) unless build deps are preinstalled.
  5. Pin to a version of the package that ships a wheel for your platform, or use a binary distribution (e.g. manylinux wheel).
  6. For pure build-env issues, try `pip install <pkg> --only-binary :all:` to force wheel-only (fails fast if no wheel exists).

Example fix

// before
pip install lxml   # fails building from sdist, missing libxml2
// after
# install system deps, then upgrade build tooling
apt-get install libxml2-dev libxslt1-dev python3-dev
python -m pip install --upgrade pip setuptools wheel
pip install lxml
Defensive patterns

Strategy: try-catch

Validate before calling

# Prefer prebuilt wheels; detect absence before installing
import subprocess

def has_wheel(name, index_url=None):
    cmd = ["pip", "index", "versions", name, "--json"]
    if index_url:
        cmd += ["--index-url", index_url]
    r = subprocess.run(cmd, capture_output=True, text=True)
    return r.returncode == 0

# Also ensure build toolchain is current
subprocess.run(["python", "-m", "pip", "install", "--upgrade", "pip", "setuptools", "wheel"], check=True)

Try / catch

# Capture build failure and fall back to a binary-only install
import subprocess
try:
    subprocess.run(["pip", "install", name], check=True)
except subprocess.CalledProcessError:
    # retry forcing wheels only
    subprocess.run(["pip", "install", name, "--only-binary", ":all:"], check=True)

Prevention

When it happens

Trigger: A requirement has no prebuilt wheel for the current platform/Python, so pip falls back to building from sdist; the build fails due to missing build dependencies, a broken pyproject.toml, missing system libraries, or incompatible compiler toolchain.

Common situations: Installing C-extension packages (e.g. numpy, lxml, psycopg2, cryptography) without wheels for the target Python/platform; missing build tools (gcc, python-dev headers, Rust for cryptography); PEP 517 build isolation disabled without the build deps installed; a broken package release on PyPI.

Related errors


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

Appendix: source

Thrown at src/pip/_internal/commands/install.py:531

            else:
                # If we're not replacing an already installed pip,
                # we're not modifying it.
                modifying_pip = pip_req.satisfied_by is None
            protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)

            reqs_to_build = [
                r for r in requirement_set.requirements_to_install if not r.is_wheel
            ]

            _, build_failures = build(
                reqs_to_build,
                wheel_cache=wheel_cache,
                verify=True,
                allow_editables=True,
            )

            if build_failures:
                raise InstallWheelBuildError(build_failures)

            to_install = resolver.get_installation_order(requirement_set)

            # Check for conflicts in the package set we're installing.
            conflicts: ConflictDetails | None = None
            should_warn_about_conflicts = (
                not options.ignore_dependencies and options.warn_about_conflicts
            )
            if should_warn_about_conflicts:
                conflicts = self._determine_conflicts(to_install)

            # Don't warn about script install locations if
            # --target or --prefix has been specified
            warn_script_location = options.warn_script_location
            if options.target_dir or options.prefix_path:
                warn_script_location = False

            # Warn on late imports so we don't silently pick up a module

View on GitHub (pinned to f399c37189)