pypa/pip · error · CommandError

Failed to build one or more wheels

Error message

Failed to build one or more wheels

What it means

Raised as CommandError in WheelCommand.run() at wheel.py:174-175 when build_failures is non-empty after the build() call (wheel.py:154-159) and after attempting to copy successful wheels (wheel.py:160-173). It means one or more requirements could not be built into a wheel archive, including cases where a successfully built wheel could not be copied to the target wheel-dir (those are appended to build_failures at wheel.py:173).

Source

Thrown at src/pip/_internal/commands/wheel.py:175

            verify=(not options.no_verify),
            allow_editables=False,
        )
        for req in build_successes:
            assert req.link and req.link.is_wheel
            assert req.local_file_path
            # copy from cache to target directory
            try:
                shutil.copy(req.local_file_path, options.wheel_dir)
            except OSError as e:
                logger.warning(
                    "Failed to copy built wheel %s to %s: %s",
                    req.name,
                    options.wheel_dir,
                    e,
                )
                build_failures.append(req)
        if len(build_failures) != 0:
            raise CommandError("Failed to build one or more wheels")

        return SUCCESS

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Read the per-requirement build error printed above this line — it names the failing project and the compiler/backend error.
  2. Install system build prerequisites (compiler, python-dev headers, libffi, etc.).
  3. Remove --no-build-isolation or pre-install the project's build dependencies.
  4. Ensure the -w/--wheel-dir is writable and has free disk space.
  5. Pin to a package version that ships a wheel for your platform, or build on a compatible platform.

Example fix

# before — wheel-dir not writable, deps missing
pip wheel --no-build-isolation -w /readonly regex
# after
pip wheel -w ./wheels regex
Defensive patterns

Strategy: try-catch

Validate before calling

import os, sys
# Pre-flight: ensure wheel-dir is writable and has space
wdir = '.'
for i,a in enumerate(sys.argv):
    if a in ('-w','--wheel-dir') and i+1 < len(sys.argv):
        wdir = sys.argv[i+1]
    elif a.startswith('--wheel-dir='):
        wdir = a.split('=',1)[1]
writable = os.access(os.path.dirname(os.path.abspath(wdir)) or '.', os.W_OK)
if not writable:
    print(f'ERROR: wheel-dir {wdir} is not writable', file=sys.stderr)
    sys.exit(2)

Try / catch

import subprocess
try:
    subprocess.run(['pip','wheel','-w','./wheels','regex'], check=True)
except subprocess.CalledProcessError:
    # fallback: install build deps or pin to a wheel-bearing version
    print('wheel build failed; check build deps and disk space, or pin a prebuilt wheel')

Prevention

When it happens

Trigger: Running 'pip wheel <req>' where <req> has no prebuilt wheel and its PEP 517 build fails (missing build deps, compiler errors, broken backend), or where the output wheel-dir is not writable / disk-full so shutil.copy fails.

Common situations: Building wheels for offline distribution on a machine lacking build tools; --no-build-isolation with missing build requirements; targeting a read-only or out-of-space -w directory; pinning a source distribution with a broken setup.

Related errors


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