0
# Error Handling
1
2
Cerberus provides a comprehensive error handling system with detailed error representation, organization, and customizable formatting. The system captures precise validation failures with context and supports custom error handlers for different output formats.
3
4
## Capabilities
5
6
### ValidationError Class
7
8
Detailed representation of individual validation failures.
9
10
```python { .api }
11
class ValidationError:
12
def __init__(self, document_path, schema_path, code, rule, constraint, value, info):
13
"""
14
Create a validation error.
15
16
Parameters:
17
- document_path: Path to field within document (tuple)
18
- schema_path: Path to rule within schema (tuple)
19
- code: Error identifier code (int)
20
- rule: Rule that failed validation (str)
21
- constraint: Constraint that failed
22
- value: Value that caused failure
23
- info: Additional error details (tuple)
24
"""
25
26
@property
27
def document_path(self) -> tuple:
28
"""Path to the field within the document that caused the error"""
29
30
@property
31
def schema_path(self) -> tuple:
32
"""Path to the rule within the schema that caused the error"""
33
34
@property
35
def code(self) -> int:
36
"""Error identifier code"""
37
38
@property
39
def rule(self) -> str:
40
"""Rule that failed validation"""
41
42
@property
43
def constraint(self):
44
"""Constraint that failed"""
45
46
@property
47
def value(self):
48
"""Value that caused the failure"""
49
50
@property
51
def info(self) -> tuple:
52
"""Additional error information"""
53
54
@property
55
def field(self):
56
"""Field name from document path"""
57
58
@property
59
def child_errors(self):
60
"""List of individual errors for bulk validation errors"""
61
62
@property
63
def definitions_errors(self):
64
"""Errors mapped to definition indices for *of-rules"""
65
66
@property
67
def is_group_error(self) -> bool:
68
"""True for bulk validation errors"""
69
70
@property
71
def is_logic_error(self) -> bool:
72
"""True for *of-rule validation errors"""
73
74
@property
75
def is_normalization_error(self) -> bool:
76
"""True for normalization errors"""
77
```
78
79
### Error Collections
80
81
Specialized collections for organizing validation errors.
82
83
```python { .api }
84
class ErrorList(list):
85
"""
86
List of ValidationError instances with queryable interface.
87
Supports 'in' keyword for ErrorDefinition instances.
88
"""
89
```
90
91
### Error Trees
92
93
Hierarchical organization of validation errors.
94
95
```python { .api }
96
class ErrorTree:
97
"""Base class for organizing errors in tree structures"""
98
99
def add(self, error):
100
"""
101
Add ValidationError to tree.
102
103
Parameters:
104
- error: ValidationError to add
105
"""
106
107
def fetch_errors_from(self, path):
108
"""
109
Get all errors for a given path.
110
111
Parameters:
112
- path: Path to fetch errors for (tuple)
113
114
Returns:
115
list: Errors at the specified path
116
"""
117
118
def fetch_node_from(self, path):
119
"""
120
Get tree node for a given path.
121
122
Parameters:
123
- path: Path to fetch node for (tuple)
124
125
Returns:
126
Tree node at the specified path
127
"""
128
129
class DocumentErrorTree(ErrorTree):
130
"""Error tree following document field structure"""
131
132
class SchemaErrorTree(ErrorTree):
133
"""Error tree following schema rule structure"""
134
```
135
136
### Error Handlers
137
138
Customizable error formatting and output.
139
140
```python { .api }
141
class BaseErrorHandler:
142
"""Abstract base class for all error handlers"""
143
144
def __call__(self, errors):
145
"""
146
Format errors for output.
147
148
Parameters:
149
- errors: Errors to format
150
151
Returns:
152
Formatted error output
153
"""
154
155
def add(self, error):
156
"""
157
Add error to handler.
158
159
Parameters:
160
- error: ValidationError to add
161
"""
162
163
def extend(self, errors):
164
"""
165
Add multiple errors.
166
167
Parameters:
168
- errors: Iterable of ValidationError instances
169
"""
170
171
def emit(self, error):
172
"""
173
Optionally emit error to stream.
174
175
Parameters:
176
- error: ValidationError to emit
177
"""
178
179
def start(self, validator):
180
"""
181
Called when validation starts.
182
183
Parameters:
184
- validator: Validator instance starting validation
185
"""
186
187
def end(self, validator):
188
"""
189
Called when validation ends.
190
191
Parameters:
192
- validator: Validator instance ending validation
193
"""
194
195
class BasicErrorHandler(BaseErrorHandler):
196
"""Default error handler that returns errors as nested dict"""
197
198
@property
199
def messages(self) -> dict:
200
"""Error code to message template mapping"""
201
202
@property
203
def tree(self):
204
"""Raw error tree structure"""
205
206
@property
207
def pretty_tree(self):
208
"""Cleaned error tree for display"""
209
210
class ToyErrorHandler(BaseErrorHandler):
211
"""Minimal error handler for child validators"""
212
213
class SchemaErrorHandler(BaseErrorHandler):
214
"""Specialized error handler for schema validation errors"""
215
```
216
217
### Error Definition Constants
218
219
Pre-defined error codes and types for different validation failures.
220
221
```python { .api }
222
# Existence Errors
223
CUSTOM: ErrorDefinition # Custom validation errors (0x00)
224
DOCUMENT_MISSING: str # Document is missing
225
REQUIRED_FIELD: ErrorDefinition # Required field missing (0x02)
226
UNKNOWN_FIELD: ErrorDefinition # Unknown field present (0x03)
227
DEPENDENCIES_FIELD: ErrorDefinition # Field dependency failed (0x04)
228
DEPENDENCIES_FIELD_VALUE: ErrorDefinition # Field dependency value failed (0x05)
229
EXCLUDES_FIELD: ErrorDefinition # Field exclusion failed (0x06)
230
231
# Shape Errors
232
DOCUMENT_FORMAT: str # Document format invalid
233
EMPTY_NOT_ALLOWED: ErrorDefinition # Empty value not allowed (0x22)
234
NOT_NULLABLE: ErrorDefinition # Null value not allowed (0x23)
235
BAD_TYPE: ErrorDefinition # Type constraint failed (0x24)
236
BAD_TYPE_FOR_SCHEMA: ErrorDefinition # Schema type constraint failed (0x25)
237
ITEMS_LENGTH: ErrorDefinition # Items length constraint failed (0x26)
238
MIN_LENGTH: ErrorDefinition # Minimum length constraint failed (0x27)
239
MAX_LENGTH: ErrorDefinition # Maximum length constraint failed (0x28)
240
241
# Value Errors
242
REGEX_MISMATCH: ErrorDefinition # Regex pattern match failed (0x41)
243
MIN_VALUE: ErrorDefinition # Minimum value constraint failed (0x42)
244
MAX_VALUE: ErrorDefinition # Maximum value constraint failed (0x43)
245
UNALLOWED_VALUE: ErrorDefinition # Value not in allowed list (0x44)
246
UNALLOWED_VALUES: ErrorDefinition # Values not in allowed list (0x45)
247
FORBIDDEN_VALUE: ErrorDefinition # Value in forbidden list (0x46)
248
FORBIDDEN_VALUES: ErrorDefinition # Values in forbidden list (0x47)
249
MISSING_MEMBERS: ErrorDefinition # Required members missing (0x48)
250
251
# Processing Errors
252
NORMALIZATION: ErrorDefinition # Normalization failed (0x60)
253
COERCION_FAILED: ErrorDefinition # Type coercion failed (0x61)
254
RENAMING_FAILED: ErrorDefinition # Field renaming failed (0x62)
255
READONLY_FIELD: ErrorDefinition # Readonly field modified (0x63)
256
SETTING_DEFAULT_FAILED: ErrorDefinition # Default value setting failed (0x64)
257
258
# Group Errors
259
ERROR_GROUP: ErrorDefinition # Error group container (0x80)
260
MAPPING_SCHEMA: ErrorDefinition # Mapping schema failed (0x81)
261
SEQUENCE_SCHEMA: ErrorDefinition # Sequence schema failed (0x82)
262
KEYSRULES: ErrorDefinition # Keys rules failed (0x83)
263
VALUESRULES: ErrorDefinition # Values rules failed (0x84)
264
BAD_ITEMS: ErrorDefinition # Items constraint failed (0x8F)
265
266
# Logical Errors
267
LOGICAL: ErrorDefinition # Logical constraint failed (0x90)
268
NONEOF: ErrorDefinition # None-of constraint failed (0x91)
269
ONEOF: ErrorDefinition # One-of constraint failed (0x92)
270
ANYOF: ErrorDefinition # Any-of constraint failed (0x93)
271
ALLOF: ErrorDefinition # All-of constraint failed (0x94)
272
```
273
274
### Helper Types
275
276
```python { .api }
277
ErrorDefinition = namedtuple('ErrorDefinition', 'code rule')
278
"""Defines error types with unique code and associated rule"""
279
```
280
281
## Usage Examples
282
283
### Basic Error Handling
284
285
```python
286
from cerberus import Validator
287
288
schema = {
289
'name': {'type': 'string', 'minlength': 2},
290
'age': {'type': 'integer', 'min': 0, 'max': 150},
291
'email': {'type': 'string', 'required': True}
292
}
293
294
v = Validator(schema)
295
296
# Invalid document
297
document = {
298
'name': 'A', # Too short
299
'age': -5, # Below minimum
300
# 'email' missing # Required field missing
301
}
302
303
if not v.validate(document):
304
print("Validation failed!")
305
print("Errors:", v.errors)
306
# Output: {
307
# 'name': ['min length is 2'],
308
# 'age': ['min value is 0'],
309
# 'email': ['required field']
310
# }
311
```
312
313
### Detailed Error Information
314
315
```python
316
from cerberus import Validator
317
318
v = Validator({'name': {'type': 'string'}})
319
v.validate({'name': 123})
320
321
# Access error tree for detailed information
322
error_tree = v.document_error_tree
323
print(error_tree.errors)
324
325
# Access individual validation errors
326
for error in error_tree.errors:
327
print(f"Field: {error.field}")
328
print(f"Rule: {error.rule}")
329
print(f"Code: {error.code}")
330
print(f"Value: {error.value}")
331
print(f"Path: {error.document_path}")
332
```
333
334
### Custom Error Handler
335
336
```python
337
from cerberus import Validator
338
from cerberus.errors import BaseErrorHandler
339
340
class CustomErrorHandler(BaseErrorHandler):
341
def __call__(self, errors):
342
"""Return simple list of error messages"""
343
messages = []
344
for field_errors in errors.values():
345
messages.extend(field_errors)
346
return messages
347
348
# Use custom handler
349
v = Validator({'name': {'type': 'string'}}, error_handler=CustomErrorHandler)
350
v.validate({'name': 123})
351
print(v.errors) # ['must be of string type']
352
```
353
354
### Error Handler with Initialization
355
356
```python
357
from cerberus import Validator
358
from cerberus.errors import BasicErrorHandler
359
360
# Pass handler as tuple with initialization arguments
361
error_handler_config = (BasicErrorHandler, {'some_option': 'value'})
362
v = Validator(schema, error_handler=error_handler_config)
363
```
364
365
### Error Tree Navigation
366
367
```python
368
from cerberus import Validator
369
370
schema = {
371
'user': {
372
'type': 'dict',
373
'schema': {
374
'name': {'type': 'string'},
375
'contacts': {
376
'type': 'list',
377
'schema': {
378
'type': 'dict',
379
'schema': {
380
'type': {'type': 'string', 'allowed': ['email', 'phone']},
381
'value': {'type': 'string'}
382
}
383
}
384
}
385
}
386
}
387
}
388
389
document = {
390
'user': {
391
'name': 123, # Invalid type
392
'contacts': [
393
{'type': 'invalid', 'value': 'test@example.com'}, # Invalid type
394
{'type': 'email'} # Missing value
395
]
396
}
397
}
398
399
v = Validator(schema)
400
v.validate(document)
401
402
# Navigate error tree
403
error_tree = v.document_error_tree
404
405
# Get errors for specific paths
406
name_errors = error_tree.fetch_errors_from(('user', 'name'))
407
contact_errors = error_tree.fetch_errors_from(('user', 'contacts', 0, 'type'))
408
409
print("Name errors:", name_errors)
410
print("Contact type errors:", contact_errors)
411
```
412
413
### Error Code Checking
414
415
```python
416
from cerberus import Validator
417
from cerberus.errors import BAD_TYPE, REQUIRED_FIELD
418
419
v = Validator({'name': {'type': 'string', 'required': True}})
420
v.validate({'name': 123})
421
422
# Check if specific error types occurred
423
error_tree = v.document_error_tree
424
errors = error_tree.errors
425
426
for error in errors:
427
if error.code == BAD_TYPE.code:
428
print(f"Type error in field {error.field}: expected string, got {type(error.value).__name__}")
429
elif error.code == REQUIRED_FIELD.code:
430
print(f"Missing required field: {error.field}")
431
```
432
433
### Error Emission and Streaming
434
435
```python
436
from cerberus import Validator
437
from cerberus.errors import BaseErrorHandler
438
import sys
439
440
class StreamingErrorHandler(BaseErrorHandler):
441
def emit(self, error):
442
"""Emit errors to stderr as they occur"""
443
print(f"Validation error: {error.field} - {error.rule}", file=sys.stderr)
444
445
def __call__(self, errors):
446
"""Return standard error format"""
447
return errors
448
449
v = Validator({'name': {'type': 'string'}}, error_handler=StreamingErrorHandler)
450
# Errors will be printed to stderr during validation
451
v.validate({'name': 123})
452
```
453
454
### Pretty Error Trees
455
456
```python
457
from cerberus import Validator
458
from cerberus.errors import BasicErrorHandler
459
460
v = Validator({'user': {'type': 'dict', 'schema': {'name': {'type': 'string'}}}})
461
v.validate({'user': {'name': 123}})
462
463
# Access pretty-formatted error tree
464
if hasattr(v.error_handler, 'pretty_tree'):
465
pretty_errors = v.error_handler.pretty_tree
466
print("Pretty errors:", pretty_errors)
467
```