0
# Error Handling
1
2
Cibuildwheel provides a structured exception hierarchy with specific error types and return codes for different failure scenarios.
3
4
## Capabilities
5
6
### Base Exception
7
8
Foundation exception class for all cibuildwheel-specific errors.
9
10
```python { .api }
11
class FatalError(BaseException):
12
return_code: int = 1
13
14
def __init__(self, *args: object) -> None:
15
"""
16
Initialize a fatal error.
17
18
Args:
19
*args: Error message arguments
20
"""
21
```
22
23
### Configuration Errors
24
25
Errors related to invalid or conflicting configuration.
26
27
```python { .api }
28
class ConfigurationError(FatalError):
29
return_code: int = 2
30
31
"""
32
Raised when configuration is invalid or conflicting.
33
34
Examples:
35
- Invalid platform specified
36
- Conflicting command-line arguments
37
- Invalid build selectors
38
- Missing required configuration
39
"""
40
```
41
42
### Build Selection Errors
43
44
Errors when no builds match the selection criteria.
45
46
```python { .api }
47
class NothingToDoError(FatalError):
48
return_code: int = 3
49
50
"""
51
Raised when no builds match the selection criteria.
52
53
Examples:
54
- All builds filtered out by skip patterns
55
- No builds available for specified platform/architecture
56
- Empty build matrix after filtering
57
"""
58
```
59
60
### Deprecation Errors
61
62
Errors for deprecated configuration or usage patterns.
63
64
```python { .api }
65
class DeprecationError(FatalError):
66
return_code: int = 4
67
68
"""
69
Raised when deprecated features are used.
70
71
Examples:
72
- Deprecated Python versions (< 3.8)
73
- Deprecated configuration options
74
- Deprecated command syntax
75
"""
76
```
77
78
### Wheel Type Errors
79
80
Errors related to wheel types and platform compatibility.
81
82
```python { .api }
83
class NonPlatformWheelError(FatalError):
84
return_code: int = 5
85
86
"""
87
Raised when a non-platform wheel is detected where platform wheel expected.
88
89
Examples:
90
- Pure Python wheel when native wheel expected
91
- Universal wheel when platform-specific wheel required
92
"""
93
94
class AlreadyBuiltWheelError(FatalError):
95
return_code: int = 6
96
97
"""
98
Raised when a wheel already exists and overwriting is disabled.
99
100
Examples:
101
- Wheel exists in output directory
102
- Incremental build with existing artifacts
103
"""
104
```
105
106
### Container Engine Errors
107
108
Errors related to Docker/Podman container operations.
109
110
```python { .api }
111
class OCIEngineTooOldError(FatalError):
112
return_code: int = 7
113
114
"""
115
Raised when the container engine version is too old.
116
117
Examples:
118
- Docker version lacks required features
119
- Podman version incompatible with cibuildwheel
120
- Missing container runtime capabilities
121
"""
122
```
123
124
### Wheel Repair Errors
125
126
Errors during the wheel repair process.
127
128
```python { .api }
129
class RepairStepProducedNoWheelError(FatalError):
130
return_code: int = 8
131
132
"""
133
Raised when wheel repair produces no output wheel.
134
135
Examples:
136
- auditwheel repair fails to create wheel
137
- delocate repair removes wheel entirely
138
- Custom repair command produces no output
139
"""
140
141
class RepairStepProducedMultipleWheelsError(FatalError):
142
return_code: int = 8
143
144
"""
145
Raised when wheel repair produces multiple wheels unexpectedly.
146
147
Examples:
148
- Repair process splits wheel into multiple files
149
- Custom repair command creates additional wheels
150
- Unexpected wheel multiplication during repair
151
"""
152
```
153
154
## Error Return Codes
155
156
Cibuildwheel uses specific exit codes to indicate different error types:
157
158
| Code | Error Type | Description |
159
|------|------------|-------------|
160
| 0 | Success | Build completed successfully |
161
| 1 | FatalError | General fatal error |
162
| 2 | ConfigurationError | Invalid configuration |
163
| 3 | NothingToDoError | No builds to execute |
164
| 4 | DeprecationError | Deprecated features used |
165
| 5 | NonPlatformWheelError | Unexpected wheel type |
166
| 6 | AlreadyBuiltWheelError | Wheel already exists |
167
| 7 | OCIEngineTooOldError | Container engine too old |
168
| 8 | RepairStepError | Wheel repair failed |
169
170
## Common Error Scenarios
171
172
### Configuration Errors
173
174
```python
175
# Invalid platform specification
176
cibuildwheel --platform invalid_platform
177
# ConfigurationError: Unsupported platform: invalid_platform
178
179
# Conflicting options
180
cibuildwheel --only cp311-linux_x86_64 --platform windows
181
# ConfigurationError: --platform cannot be specified with --only
182
183
# Invalid architecture
184
cibuildwheel --archs invalid_arch
185
# ConfigurationError: Invalid architecture specification
186
```
187
188
### Build Selection Errors
189
190
```python
191
# No builds match criteria
192
CIBW_BUILD = "cp37-*" # Python 3.7 not supported in v3.x
193
# NothingToDoError: No build identifiers selected
194
195
# All builds skipped
196
CIBW_SKIP = "*"
197
# NothingToDoError: No build identifiers selected
198
199
# Architecture not available
200
cibuildwheel --platform linux --archs nonexistent_arch
201
# NothingToDoError: No builds available for specified architecture
202
```
203
204
### Deprecation Errors
205
206
```python
207
# Deprecated Python version
208
CIBW_BUILD = "cp36-*"
209
# DeprecationError: Python 3.6 no longer supported
210
211
# Deprecated configuration format
212
CIBW_TEST_COMMAND = "python {python} -m pytest"
213
# DeprecationError: {python} placeholder no longer supported
214
```
215
216
### Container Engine Errors
217
218
```python
219
# Docker too old
220
# OCIEngineTooOldError: Docker version 19.03+ required
221
222
# Podman configuration issue
223
# OCIEngineTooOldError: Podman not properly configured
224
```
225
226
## Error Handling Patterns
227
228
### Try-Catch Error Handling
229
230
```python
231
from cibuildwheel import main
232
from cibuildwheel.errors import (
233
ConfigurationError,
234
NothingToDoError,
235
FatalError
236
)
237
238
try:
239
main()
240
except ConfigurationError as e:
241
print(f"Configuration error: {e}")
242
sys.exit(2)
243
except NothingToDoError as e:
244
print(f"Nothing to build: {e}")
245
sys.exit(3)
246
except FatalError as e:
247
print(f"Fatal error: {e}")
248
sys.exit(e.return_code)
249
```
250
251
### CI Integration Error Handling
252
253
```yaml
254
# GitHub Actions
255
- name: Build wheels
256
run: python -m cibuildwheel --output-dir wheelhouse
257
continue-on-error: false
258
259
- name: Handle no builds
260
if: failure() && contains(github.event.head_commit.message, '[allow-empty]')
261
run: |
262
echo "No builds to execute, but allowed by commit message"
263
exit 0
264
```
265
266
### Conditional Error Handling
267
268
```python
269
import os
270
from cibuildwheel.errors import NothingToDoError
271
272
try:
273
# Run cibuildwheel
274
main()
275
except NothingToDoError as e:
276
# Check if empty builds are allowed
277
if os.environ.get("CIBW_ALLOW_EMPTY"):
278
print(f"No builds to execute: {e}")
279
sys.exit(0) # Success despite no builds
280
else:
281
raise # Re-raise as error
282
```
283
284
## Error Prevention
285
286
### Configuration Validation
287
288
```python
289
# Validate configuration before running
290
from cibuildwheel.options import compute_options
291
from cibuildwheel.errors import ConfigurationError
292
293
try:
294
options = compute_options(platform, args, env)
295
print("Configuration is valid")
296
except ConfigurationError as e:
297
print(f"Configuration validation failed: {e}")
298
```
299
300
### Build Selection Validation
301
302
```python
303
# Check if any builds will be selected
304
from cibuildwheel.selector import BuildSelector
305
306
build_selector = BuildSelector(
307
build_config="cp311-*",
308
skip_config="*-win32"
309
)
310
311
# Test against known identifiers
312
test_ids = ["cp311-linux_x86_64", "cp311-win_amd64", "cp311-win32"]
313
matching_builds = [id for id in test_ids if build_selector(id)]
314
315
if not matching_builds:
316
print("Warning: No builds will be selected")
317
```
318
319
### Environment Validation
320
321
```python
322
# Validate environment before building
323
import shutil
324
import sys
325
326
# Check required tools
327
if not shutil.which("python"):
328
print("Error: Python not found in PATH")
329
sys.exit(1)
330
331
# Check platform-specific requirements
332
if sys.platform == "linux":
333
if not shutil.which("docker") and not shutil.which("podman"):
334
print("Error: Docker or Podman required for Linux builds")
335
sys.exit(1)
336
```
337
338
## Debugging Errors
339
340
### Enable Debug Output
341
342
```bash
343
# Full tracebacks for all errors
344
cibuildwheel --debug-traceback
345
346
# Environment variable equivalent
347
export CIBW_DEBUG_TRACEBACK=1
348
```
349
350
### Verbose Configuration Display
351
352
```bash
353
# Print build identifiers without building
354
cibuildwheel --print-build-identifiers
355
356
# Shows what would be built with current configuration
357
```
358
359
### Error Context
360
361
```python
362
# Most cibuildwheel errors include helpful context
363
try:
364
main()
365
except ConfigurationError as e:
366
# Error message includes:
367
# - What configuration was invalid
368
# - Expected values or format
369
# - Suggestions for fixing
370
print(f"Detailed error: {e}")
371
```
372
373
## Custom Error Handling
374
375
### Wrapper Functions
376
377
```python
378
def safe_cibuildwheel(platform=None, **kwargs):
379
"""Wrapper around cibuildwheel with custom error handling."""
380
try:
381
return main()
382
except NothingToDoError:
383
print("No wheels to build for current configuration")
384
return 0 # Treat as success
385
except ConfigurationError as e:
386
print(f"Please check your cibuildwheel configuration: {e}")
387
return 2
388
except FatalError as e:
389
print(f"Build failed: {e}")
390
return e.return_code
391
```
392
393
### Logging Integration
394
395
```python
396
import logging
397
from cibuildwheel.errors import FatalError
398
399
logging.basicConfig(level=logging.INFO)
400
logger = logging.getLogger(__name__)
401
402
try:
403
main()
404
except FatalError as e:
405
logger.error(f"Cibuildwheel failed with code {e.return_code}: {e}")
406
raise
407
```