Skip to content

Commit 5a1296c

Browse files
committed
Update build failures document
1 parent ff91cf7 commit 5a1296c

File tree

2 files changed

+288
-50
lines changed

2 files changed

+288
-50
lines changed

docs/reference/build_failures.md

Lines changed: 287 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,300 @@
1-
# Build failures
1+
# Troubleshooting build failures
22

3-
This page lists common reasons why resolution and installation fails with a build error and how to
4-
fix them.
3+
uv needs to build packages when there is not a compatible wheel (a pre-built distribution of the
4+
package) available. Building packages can fail for many reasons.
55

6-
### Why does uv build a package?
6+
## Recognizing a build failure
7+
8+
An example build failure can be produced by trying to install and old version of numpy on a new,
9+
unsupported version of Python:
10+
11+
```console
12+
$ uv pip install -p 3.13 'numpy<1.20'
13+
Resolved 1 package in 62ms
14+
× Failed to download and build `numpy==1.19.5`
15+
├─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
16+
17+
│ [stderr]
18+
│ Traceback (most recent call last):
19+
│ File "<string>", line 8, in <module>
20+
│ from setuptools.build_meta import __legacy__ as backend
21+
│ File "/Users/example/.cache/uv/builds-v0/.tmp96A0WB/lib/python3.13/site-packages/setuptools/__init__.py", line 9, in <module>
22+
│ import distutils.core
23+
│ ModuleNotFoundError: No module named 'distutils'
24+
25+
╰─▶ distutils was removed from the standard library in Python 3.12. Consider adding a constraint
26+
(like `numpy >1.19.5`) to avoid building a version of numpy that depends on distutils.
27+
```
28+
29+
Notice that the error message is prefaced by "Build backend failed to determine requirements".
30+
31+
The build failure includes the `[stderr]` (and `[stdout]`, if present) from the build backend that
32+
was used for the build. The error logs are not from uv itself.
33+
34+
The message following the `╰─▶` is a hint provided by uv, to help resolve common build failures. A
35+
hint will not be available for all build failures.
36+
37+
## Confirming that a build failure is specific to uv
38+
39+
Build failures are usually related to your system and the build backend. It is rare that a build
40+
failure is specific to uv. You can confirm that the build failure is not related to uv by attempting
41+
to reproduce it with pip:
42+
43+
```console
44+
$ uv venv -p 3.13 --seed
45+
$ source .venv/bin/activate
46+
$ pip install --use-pep517 'numpy==1.19.5'
47+
Collecting numpy==1.19.5
48+
Using cached numpy-1.19.5.zip (7.3 MB)
49+
Installing build dependencies ... done
50+
Getting requirements to build wheel ... done
51+
ERROR: Exception:
52+
Traceback (most recent call last):
53+
...
54+
File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py", line 321, in _call_hook
55+
raise BackendUnavailable(data.get('traceback', ''))
56+
pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
57+
File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 77, in _build_backend
58+
obj = import_module(mod_path)
59+
File "/Users/example/.local/share/uv/python/cpython-3.13.0-macos-aarch64-none/lib/python3.13/importlib/__init__.py", line 88, in import_module
60+
return _bootstrap._gcd_import(name[level:], package, level)
61+
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62+
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
63+
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
64+
File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
65+
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
66+
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
67+
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
68+
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
69+
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
70+
File "<frozen importlib._bootstrap_external>", line 1022, in exec_module
71+
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
72+
File "/private/var/folders/6p/k5sd5z7j31b31pq4lhn0l8d80000gn/T/pip-build-env-vdpjme7d/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 9, in <module>
73+
import distutils.core
74+
ModuleNotFoundError: No module named 'distutils'
75+
```
76+
77+
!!! important
78+
79+
The `--use-pep517` flag should be included with the `pip install` invocation to ensure the same
80+
build isolation behavior. uv always uses [build isolation by default](https://docs.astral.sh/uv/pip/compatibility/#pep-517-build-isolation).
81+
82+
We also recommend including the `--force-reinstall` and `--no-cache` options when reproducing
83+
failures.
84+
85+
Since this build failure occurs in pip too, it is not likely to be a bug with uv.
86+
87+
If a build failure is reproducible with another installer, you should file an issue upstream (in
88+
this example, with `numpy` or `setuptools`), find a way to avoid building the package in the first
89+
place, or make the necessary adjustments to your system for the build to succeed.
90+
91+
## Why does uv build a package?
792

893
When generating the cross-platform lockfile, uv needs to determine the dependencies of all packages,
994
even those only installed on other platforms. uv tries to avoid package builds during resolution. It
1095
uses any wheel if exist for that version, then tries to find static metadata in the source
1196
distribution (mainly pyproject.toml with static `project.version`, `project.dependencies` and
12-
`project.optional-dependencies` or METADATA of at least version 2.2). Only if all of that fails, it
13-
builds the package.
97+
`project.optional-dependencies` or METADATA v2.2+). Only if all of that fails, it builds the
98+
package.
1499

15100
When installing, uv needs to have a wheel for the current platform for each package. If no matching
16101
wheel exists in the index, uv tries to build the source distribution.
17102

18103
You can check which wheels exist for a PyPI project under “Download Files”, e.g.
19104
https://pypi.org/project/numpy/2.1.1/#files. Wheels with `...-py3-none-any.whl` filenames work
20-
everywhere, others have the operating system and platform in the filename. For the linked numpy
21-
version, you can see that Python 3.10 to 3.13 on MacOS, Linux and Windows are supported.
22-
23-
### Fixes and Workarounds
24-
25-
- If the build error mentions a missing header or library, there is often a matching package in your
26-
system package manager.
27-
28-
Example: When `uv pip install mysqlclient==2.2.4` fails on Ubuntu, you need to run
29-
`sudo apt install default-libmysqlclient-dev build-essential pkg-config` to install the MySQL
30-
headers ([https://pypi.org/project/mysqlclient/2.2.4/](https://pypi.org/project/mysqlclient/2.2.4/#Linux))
31-
32-
- If the build error mentions a failing import, consider
33-
[deactivating build isolation](https://docs.astral.sh/uv/concepts/projects/#build-isolation).
34-
- If a package fails to build during resolution and the version that failed to build is older than
35-
the version you want to use, try adding a
36-
[constraint](https://docs.astral.sh/uv/reference/settings/#constraint-dependencies) with a lower
37-
bound (e.g. `numpy>=1.17`). Sometimes, due to algorithmic limitations, the uv resolver tries to
38-
find a fitting version using unreasonably old packages, which can be prevented by using lower
39-
bounds.
40-
- Consider using a different Python version for locking and/or installation (`-p`). If you are using
41-
an older Python version, you may need to use an older version of certain packages with native code
42-
too, especially for scientific code. Example: torch 1.12.0 support Python 3.7 to 3.10
43-
(https://pypi.org/project/torch/1.12.0/#files), while numpy 2.1.0 supports Python 3.10 to 3.13
44-
(https://numpy.org/doc/stable/release/2.1.0-notes.html#numpy-2-1-0-release-notes), so both
45-
together mean you need Python 3.10 (or upgrade torch).
46-
- If locking fails due to building a package from a platform you do not support, consider
47-
[declaring resolver environments](https://docs.astral.sh/uv/reference/settings/#environments) with
48-
your supported platforms.
49-
- If you support a large range of Python versions, consider using markers to use older versions for
50-
older Python versions and newer versions for newer Python version. In the example, numpy tends to
51-
support four Python minor version at a time, so to support Python 3.8 to 3.13, the versions need
52-
to be split:
53-
54-
```
55-
numpy>=1.23; python_version >= "3.10"
56-
numpy<1.23; python_version < "3.10"
57-
```
58-
59-
- If locking fails due to building a package from a different platform, as an escape hatch you can
60-
[provide dependency metadata manually](https://docs.astral.sh/uv/reference/settings/#dependency-metadata).
61-
As uv can not verify this information, it is important to specify correct metadata in this
62-
override.
105+
everywhere, others have the operating system and platform in the filename. In the linked `numpy`
106+
example, you can see that there are pre-built distributions for Python 3.10 to 3.13 on MacOS, Linux
107+
and Windows.
108+
109+
## Common build failures
110+
111+
The following examples demonstrate common build failures and how to resolve them.
112+
113+
### Command is not found
114+
115+
If the build error mentions a missing command, for example, `gcc`:
116+
117+
<!-- docker run --platform linux/x86_64 -it ghcr.io/astral-sh/uv:python3.10-bookworm-slim /bin/bash -c "uv pip install --system pysha3==1.0.2" -->
118+
119+
```hl_lines="17"
120+
× Failed to download and build `pysha3==1.0.2`
121+
╰─▶ Build backend failed to build wheel through `build_wheel` (exit status: 1)
122+
123+
[stdout]
124+
running bdist_wheel
125+
running build
126+
running build_py
127+
creating build/lib.linux-x86_64-cpython-310
128+
copying sha3.py -> build/lib.linux-x86_64-cpython-310
129+
running build_ext
130+
building '_pysha3' extension
131+
creating build/temp.linux-x86_64-cpython-310/Modules/_sha3
132+
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -DPY_WITH_KECCAK=1 -I/root/.cache/uv/builds-v0/.tmpxAJdUa/include -I/usr/local/include/python3.10 -c Modules/_sha3/sha3module.c -o
133+
build/temp.linux-x86_64-cpython-310/Modules/_sha3/sha3module.o
134+
135+
[stderr]
136+
error: command 'gcc' failed: No such file or directory
137+
```
138+
139+
Then, you'll need to install it with your system package manager, e.g., to resolve the error above:
140+
141+
```console
142+
$ apt-get install gcc
143+
```
144+
145+
!!! note
146+
147+
When using the uv-managed Python versions, it's common to need `clang` installed instead of
148+
`gcc`.
149+
150+
### Header or library is missing
151+
152+
If the build error mentions a missing header or library, e.g., a `.h` file, then you'll need to
153+
install it with your system package manager.
154+
155+
For example, installing `pygraphviz` requires Graphviz to be installed:
156+
157+
<!-- docker run --platform linux/x86_64 -it ghcr.io/astral-sh/uv:python3.12-bookworm /bin/bash -c "uv pip install --system 'pygraphviz'" -->
158+
159+
```hl_lines="18-19"
160+
× Failed to download and build `pygraphviz==1.14`
161+
╰─▶ Build backend failed to build wheel through `build_wheel` (exit status: 1)
162+
163+
[stdout]
164+
running bdist_wheel
165+
running build
166+
running build_py
167+
...
168+
gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -DSWIG_PYTHON_STRICT_BYTE_CHAR -I/root/.cache/uv/builds-v0/.tmpgLYPe0/include -I/usr/local/include/python3.12 -c pygraphviz/graphviz_wrap.c -o
169+
build/temp.linux-x86_64-cpython-312/pygraphviz/graphviz_wrap.o
170+
171+
[stderr]
172+
...
173+
pygraphviz/graphviz_wrap.c:9: warning: "SWIG_PYTHON_STRICT_BYTE_CHAR" redefined
174+
9 | #define SWIG_PYTHON_STRICT_BYTE_CHAR
175+
|
176+
<command-line>: note: this is the location of the previous definition
177+
pygraphviz/graphviz_wrap.c:3023:10: fatal error: graphviz/cgraph.h: No such file or directory
178+
3023 | #include "graphviz/cgraph.h"
179+
| ^~~~~~~~~~~~~~~~~~~
180+
compilation terminated.
181+
error: command '/usr/bin/gcc' failed with exit code 1
182+
183+
hint: This error likely indicates that you need to install a library that provides "graphviz/cgraph.h" for `[email protected]`
184+
```
185+
186+
To resolve this error on Debian, you'd install the `libgraphviz-dev` package:
187+
188+
```console
189+
$ apt install libgraphviz-dev
190+
```
191+
192+
Note that installing the `graphviz` package is not sufficient, the development headers need to be
193+
installed.
194+
195+
!!! tip
196+
197+
To resolve an error where `Python.h` is missing, install the [`python3-dev` package](https://packages.debian.org/bookworm/python3-dev).
198+
199+
### Module is missing or cannot be imported
200+
201+
If the build error mentions a failing import, consider
202+
[disabling build isolation](../concepts/projects/config/#build-isolation).
203+
204+
For example, some packages assume that `pip` is available without declaring it as a build
205+
dependency:
206+
207+
<!-- docker run --platform linux/x86_64 -it ghcr.io/astral-sh/uv:python3.12-bookworm-slim /bin/bash -c "uv pip install --system chumpy" -->
208+
209+
```hl_lines="7"
210+
× Failed to download and build `chumpy==0.70`
211+
╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
212+
213+
[stderr]
214+
Traceback (most recent call last):
215+
File "<string>", line 9, in <module>
216+
ModuleNotFoundError: No module named 'pip'
217+
218+
During handling of the above exception, another exception occurred:
219+
220+
Traceback (most recent call last):
221+
File "<string>", line 14, in <module>
222+
File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 334, in get_requires_for_build_wheel
223+
return self._get_build_requires(config_settings, requirements=[])
224+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
225+
File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 304, in _get_build_requires
226+
self.run_setup()
227+
File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 522, in run_setup
228+
super().run_setup(setup_script=setup_script)
229+
File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 320, in run_setup
230+
exec(code, locals())
231+
File "<string>", line 11, in <module>
232+
ModuleNotFoundError: No module named 'pip'
233+
```
234+
235+
To resolve this error, pre-install the build dependencies then disable build isolation for the
236+
package:
237+
238+
```console
239+
$ uv pip install pip setuptools
240+
$ uv pip install chumpy --no-build-isolation-package chumpy
241+
```
242+
243+
Note you will need to install the missing package, e.g., `pip`, _and_ all the other build
244+
dependencies of the package, e.g, `setuptools`.
245+
246+
### Old version of the package is built
247+
248+
If a package fails to build during resolution and the version that failed to build is older than the
249+
version you want to use, try adding a [constraint](./settings/#constraint-dependencies) with a lower
250+
bound (e.g. `numpy>=1.17`). Sometimes, due to algorithmic limitations, the uv resolver tries to find
251+
a fitting version using unreasonably old packages, which can be prevented by using lower bounds.
252+
253+
For example, when resolving the following dependencies on Python 3.10, uv attempts to build an old
254+
version of `apache-beam`.
255+
256+
```title="requirements.txt"
257+
dill<0.3.9,>=0.2.2
258+
apache-beam<=2.49.0
259+
```
260+
261+
<!-- docker run --platform linux/x86_64 -it ghcr.io/astral-sh/uv:python3.10-bookworm-slim /bin/bash -c "printf 'dill<0.3.9,>=0.2.2\napache-beam<=2.49.0' | uv pip compile -" -->
262+
263+
```hl_lines="1"
264+
× Failed to download and build `apache-beam==2.0.0`
265+
╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
266+
267+
[stderr]
268+
...
269+
```
270+
271+
Adding a lower bound constraint, e.g., `apache-beam<=2.49.0,>2.30.0`, resolves this build failure as
272+
uv will avoid using an old version of `apache-beam`.
273+
274+
Constraints can also be defined for indirect dependencies using `constraints.txt` files or the
275+
[`constraint-dependencies`](./settings.md#constraint-dependencies) setting.
276+
277+
### Package is only needed for an unused platform
278+
279+
If locking fails due to building a package from a platform you do not need to support, consider
280+
[limiting resolution](../concepts/projects/config/#limited-resolution-environments) to your
281+
supported platforms.
282+
283+
### Package does not support all Python versions
284+
285+
If you support a large range of Python versions, consider using markers to use older versions for
286+
older Python versions and newer versions for newer Python version. For example, `numpy` only
287+
supports four Python minor version at a time, so to support a wider range of Python versions, e.g.,
288+
Python 3.8 to 3.13, the `numpy` requirement needs to be split:
289+
290+
```
291+
numpy>=1.23; python_version >= "3.10"
292+
numpy<1.23; python_version < "3.10"
293+
```
294+
295+
### Package is only usable on a specific platform
296+
297+
If locking fails due to building a package that is only usable on another platform, you can
298+
[provide dependency metadata manually](https://docs.astral.sh/uv/reference/settings/#dependency-metadata)
299+
to skip the build. uv can not verify this information, so it is important to specify correct
300+
metadata when using this override.

mkdocs.template.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ nav:
145145
- reference/index.md
146146
- Commands: reference/cli.md
147147
- Settings: reference/settings.md
148-
- Build Failures: reference/build_failures.md
148+
- Build failures: reference/build_failures.md
149149
- Resolver: reference/resolver-internals.md
150150
- Benchmarks: reference/benchmarks.md
151151
- Versioning: reference/versioning.md

0 commit comments

Comments
 (0)