0
# Error Handling
1
2
Comprehensive exception hierarchy and error reporting system for JSON Schema validation. This module provides detailed validation failure information, error organization, and utilities for error analysis.
3
4
## Capabilities
5
6
### Base Error Class
7
8
Internal base class for jsonschema errors. Both ValidationError and SchemaError inherit from this class.
9
10
```python { .api }
11
class _Error(Exception):
12
"""Base class for jsonschema validation and schema errors."""
13
14
message: Any
15
path: Any
16
schema_path: Any
17
context: Any
18
cause: Any
19
validator: Any
20
validator_value: Any
21
instance: Any
22
schema: Any
23
parent: Any
24
25
def __init__(
26
self,
27
message: str,
28
validator: str | None = None,
29
path: Sequence[str | int] | None = None,
30
cause: Exception | None = None,
31
context: list[ValidationError] | None = None,
32
validator_value: Any = None,
33
instance: Any = None,
34
schema: dict | None = None,
35
schema_path: Sequence[str] | None = None,
36
parent: ValidationError | None = None
37
) -> None: ...
38
39
def __unicode__(self) -> str:
40
"""Return unicode representation of the error."""
41
42
@classmethod
43
def create_from(cls, other: _Error) -> _Error:
44
"""Create a new error from another error."""
45
46
@property
47
def absolute_path(self) -> Sequence[str | int]:
48
"""Absolute path to the failing instance."""
49
50
@property
51
def absolute_schema_path(self) -> Sequence[str]:
52
"""Absolute path to the failing schema keyword."""
53
```
54
55
### Base Validation Error
56
57
Main exception raised when JSON Schema validation fails. Inherits from _Error.
58
59
```python { .api }
60
class ValidationError(_Error):
61
"""Exception raised when JSON Schema validation fails."""
62
63
message: str
64
path: Sequence[str | int]
65
schema_path: Sequence[str]
66
context: list[ValidationError]
67
cause: Exception | None
68
validator: str
69
validator_value: Any
70
instance: Any
71
schema: dict
72
parent: ValidationError | None
73
74
def __init__(
75
self,
76
message: str,
77
validator: str | None = None,
78
path: Sequence[str | int] | None = None,
79
cause: Exception | None = None,
80
context: list[ValidationError] | None = None,
81
validator_value: Any = None,
82
instance: Any = None,
83
schema: dict | None = None,
84
schema_path: Sequence[str] | None = None,
85
parent: ValidationError | None = None
86
) -> None:
87
"""
88
Initialize validation error.
89
90
Args:
91
message: Human-readable error message
92
validator: Name of the failing validator
93
path: Path to the failing instance
94
cause: Underlying exception that caused this error
95
context: List of sub-errors
96
validator_value: Value of the failing validator in schema
97
instance: The failing instance value
98
schema: Schema that failed validation
99
schema_path: Path to the failing schema keyword
100
parent: Parent error in error hierarchy
101
"""
102
103
@classmethod
104
def create_from(cls, other: ValidationError) -> ValidationError:
105
"""Create a new ValidationError from another error."""
106
107
@property
108
def absolute_path(self) -> Sequence[str | int]:
109
"""Absolute path to the failing instance."""
110
111
@property
112
def absolute_schema_path(self) -> Sequence[str]:
113
"""Absolute path to the failing schema keyword."""
114
```
115
116
Usage example:
117
118
```python
119
from jsonschema import Draft7Validator, ValidationError
120
121
schema = {
122
"type": "object",
123
"properties": {
124
"age": {"type": "integer", "minimum": 0}
125
},
126
"required": ["name"]
127
}
128
129
validator = Draft7Validator(schema)
130
data = {"age": -5}
131
132
try:
133
validator.validate(data)
134
except ValidationError as e:
135
print(f"Message: {e.message}")
136
print(f"Path: {'.'.join(str(p) for p in e.path)}")
137
print(f"Schema path: {'.'.join(e.schema_path)}")
138
print(f"Validator: {e.validator}")
139
print(f"Failed value: {e.instance}")
140
```
141
142
### Schema Definition Error
143
144
Exception raised when a JSON schema itself is invalid.
145
146
```python { .api }
147
class SchemaError(_Error):
148
"""Exception raised when a schema is invalid."""
149
150
message: str
151
path: Sequence[str | int]
152
schema_path: Sequence[str]
153
context: list[ValidationError]
154
cause: Exception | None
155
validator: str
156
validator_value: Any
157
instance: Any
158
schema: dict
159
parent: ValidationError | None
160
161
def __init__(
162
self,
163
message: str,
164
validator: str | None = None,
165
path: Sequence[str | int] | None = None,
166
cause: Exception | None = None,
167
context: list[ValidationError] | None = None,
168
validator_value: Any = None,
169
instance: Any = None,
170
schema: dict | None = None,
171
schema_path: Sequence[str] | None = None,
172
parent: ValidationError | None = None
173
) -> None: ...
174
175
@classmethod
176
def create_from(cls, other: ValidationError) -> SchemaError: ...
177
178
@property
179
def absolute_path(self) -> Sequence[str | int]: ...
180
181
@property
182
def absolute_schema_path(self) -> Sequence[str]: ...
183
```
184
185
Usage example:
186
187
```python
188
from jsonschema import Draft7Validator, SchemaError
189
190
# Invalid schema - type should be a string, not a list
191
invalid_schema = {
192
"type": ["string", "number", "invalid"] # "invalid" is not a valid type
193
}
194
195
try:
196
validator = Draft7Validator(invalid_schema)
197
validator.check_schema(invalid_schema)
198
except SchemaError as e:
199
print(f"Schema error: {e.message}")
200
print(f"Schema path: {'.'.join(e.schema_path)}")
201
```
202
203
### Reference Resolution Error
204
205
Exception raised when JSON Schema reference ($ref) resolution fails.
206
207
```python { .api }
208
class RefResolutionError(Exception):
209
"""Exception raised when a $ref cannot be resolved."""
210
211
def __init__(self, cause: Exception) -> None:
212
"""
213
Initialize reference resolution error.
214
215
Args:
216
cause: Underlying exception that caused resolution failure
217
"""
218
219
def __lt__(self, other: RefResolutionError) -> bool:
220
"""Less than comparison for RefResolutionError instances."""
221
222
def __le__(self, other: RefResolutionError) -> bool:
223
"""Less than or equal comparison for RefResolutionError instances."""
224
225
def __gt__(self, other: RefResolutionError) -> bool:
226
"""Greater than comparison for RefResolutionError instances."""
227
228
def __ge__(self, other: RefResolutionError) -> bool:
229
"""Greater than or equal comparison for RefResolutionError instances."""
230
```
231
232
Usage example:
233
234
```python
235
from jsonschema import Draft7Validator, RefResolver, RefResolutionError
236
237
schema = {
238
"type": "object",
239
"properties": {
240
"person": {"$ref": "#/definitions/nonexistent"} # Invalid reference
241
}
242
}
243
244
try:
245
resolver = RefResolver.from_schema(schema)
246
validator = Draft7Validator(schema, resolver=resolver)
247
validator.validate({"person": {"name": "Alice"}})
248
except RefResolutionError as e:
249
print(f"Reference resolution failed: {e}")
250
```
251
252
### Format Validation Error
253
254
Exception raised when string format validation fails.
255
256
```python { .api }
257
class FormatError(Exception):
258
"""Exception raised when format validation fails."""
259
260
message: str
261
cause: Exception | None
262
263
def __init__(self, message: str, cause: Exception | None = None) -> None:
264
"""
265
Initialize format error.
266
267
Args:
268
message: Error message
269
cause: Underlying exception
270
"""
271
272
def __unicode__(self) -> str:
273
"""Return unicode representation of the format error."""
274
```
275
276
### Type Checking Errors
277
278
Exceptions related to type validation system.
279
280
```python { .api }
281
class UndefinedTypeCheck(Exception):
282
"""Exception raised when a type check is undefined."""
283
284
type: str
285
286
def __init__(self, type: str) -> None:
287
"""
288
Initialize undefined type check error.
289
290
Args:
291
type: The undefined type name
292
"""
293
294
def __unicode__(self) -> str:
295
"""Return unicode representation of the error."""
296
297
class UnknownType(Exception):
298
"""Exception raised when an unknown type is encountered."""
299
300
type: str
301
instance: Any
302
schema: dict
303
304
def __init__(self, type: str, instance: Any, schema: dict) -> None:
305
"""
306
Initialize unknown type error.
307
308
Args:
309
type: The unknown type name
310
instance: The instance being validated
311
schema: The schema containing the unknown type
312
"""
313
314
def __unicode__(self) -> str:
315
"""Return unicode representation of the error."""
316
```
317
318
### Error Tree Organization
319
320
Tree structure for organizing and navigating validation errors hierarchically.
321
322
```python { .api }
323
class ErrorTree:
324
"""Tree structure for organizing validation errors."""
325
326
errors: dict
327
328
def __init__(self, errors: Iterable[ValidationError] | None = None) -> None:
329
"""
330
Initialize error tree.
331
332
Args:
333
errors: Iterable of validation errors to organize
334
"""
335
336
def __contains__(self, index: str | int) -> bool:
337
"""Check if error exists at given index."""
338
339
def __getitem__(self, index: str | int) -> ErrorTree:
340
"""Get error subtree at given index."""
341
342
def __setitem__(self, index: str | int, value: ErrorTree) -> None:
343
"""Set error subtree at given index."""
344
345
def __iter__(self) -> Iterator[ValidationError]:
346
"""Iterate over errors in tree."""
347
348
def __len__(self) -> int:
349
"""Get number of direct errors in tree."""
350
351
@property
352
def total_errors(self) -> int:
353
"""Get total number of errors including subtrees."""
354
```
355
356
Usage example:
357
358
```python
359
from jsonschema import Draft7Validator, ErrorTree
360
361
schema = {
362
"type": "object",
363
"properties": {
364
"users": {
365
"type": "array",
366
"items": {
367
"type": "object",
368
"properties": {
369
"name": {"type": "string"},
370
"age": {"type": "integer", "minimum": 0}
371
},
372
"required": ["name", "age"]
373
}
374
}
375
}
376
}
377
378
validator = Draft7Validator(schema)
379
data = {
380
"users": [
381
{"name": "Alice"}, # Missing age
382
{"name": "Bob", "age": -5}, # Invalid age
383
{"age": 25} # Missing name
384
]
385
}
386
387
errors = validator.iter_errors(data)
388
tree = ErrorTree(errors)
389
390
# Navigate errors by path
391
if "users" in tree:
392
users_errors = tree["users"]
393
if 0 in users_errors: # First user errors
394
print(f"First user has {len(users_errors[0])} errors")
395
if 1 in users_errors: # Second user errors
396
print(f"Second user has {len(users_errors[1])} errors")
397
398
print(f"Total errors: {tree.total_errors}")
399
```
400
401
### Error Analysis Utilities
402
403
Utilities for analyzing and selecting the most relevant validation errors.
404
405
```python { .api }
406
def by_relevance(
407
weak: Callable[[ValidationError], float] = None,
408
strong: Callable[[ValidationError], float] = None
409
) -> Callable[[ValidationError], float]:
410
"""
411
Create error relevance function.
412
413
Args:
414
weak: Function to compute weak relevance score
415
strong: Function to compute strong relevance score
416
417
Returns:
418
Relevance scoring function
419
"""
420
421
def best_match(
422
errors: Iterable[ValidationError],
423
key: Callable[[ValidationError], float] = None
424
) -> ValidationError:
425
"""
426
Find the most relevant error from a collection.
427
428
Args:
429
errors: Collection of validation errors
430
key: Function to compute error relevance score
431
432
Returns:
433
Most relevant validation error
434
"""
435
436
# Default relevance function
437
relevance: Callable[[ValidationError], float]
438
439
# Constants for relevance scoring
440
WEAK_MATCHES: dict
441
STRONG_MATCHES: dict
442
```
443
444
Usage example:
445
446
```python
447
from jsonschema import Draft7Validator, best_match
448
449
schema = {
450
"type": "object",
451
"properties": {
452
"name": {"type": "string"},
453
"age": {"type": "integer", "minimum": 0, "maximum": 150}
454
},
455
"required": ["name", "age"]
456
}
457
458
validator = Draft7Validator(schema)
459
data = {"name": 123, "age": -5} # Multiple errors
460
461
errors = list(validator.iter_errors(data))
462
most_relevant = best_match(errors)
463
464
print(f"Most relevant error: {most_relevant.message}")
465
print(f"At path: {'.'.join(str(p) for p in most_relevant.path)}")
466
```
467
468
## Usage Examples
469
470
### Comprehensive Error Handling
471
472
```python
473
from jsonschema import Draft7Validator, ValidationError, ErrorTree, best_match
474
475
schema = {
476
"type": "object",
477
"properties": {
478
"profile": {
479
"type": "object",
480
"properties": {
481
"name": {"type": "string", "minLength": 1},
482
"email": {"type": "string", "format": "email"},
483
"age": {"type": "integer", "minimum": 0, "maximum": 150}
484
},
485
"required": ["name", "email"]
486
}
487
},
488
"required": ["profile"]
489
}
490
491
validator = Draft7Validator(schema)
492
data = {
493
"profile": {
494
"name": "",
495
"email": "invalid-email",
496
"age": -5
497
}
498
}
499
500
try:
501
validator.validate(data)
502
except ValidationError as e:
503
# Get all errors
504
all_errors = list(validator.iter_errors(data))
505
506
# Organize in tree structure
507
error_tree = ErrorTree(all_errors)
508
509
# Find most relevant error
510
primary_error = best_match(all_errors)
511
print(f"Primary issue: {primary_error.message}")
512
513
# Navigate specific path errors
514
if "profile" in error_tree:
515
profile_errors = error_tree["profile"]
516
for field in ["name", "email", "age"]:
517
if field in profile_errors:
518
field_errors = profile_errors[field]
519
print(f"{field} errors: {len(field_errors)}")
520
for error in field_errors:
521
print(f" - {error.message}")
522
```
523
524
### Custom Error Reporting
525
526
```python
527
from jsonschema import Draft7Validator, ValidationError
528
529
def detailed_error_report(validator, data):
530
"""Generate detailed error report with context."""
531
errors = []
532
533
for error in validator.iter_errors(data):
534
error_info = {
535
'path': '.'.join(str(p) for p in error.path),
536
'message': error.message,
537
'invalid_value': error.instance,
538
'validator': error.validator,
539
'schema_rule': error.validator_value,
540
'schema_path': '.'.join(error.schema_path)
541
}
542
errors.append(error_info)
543
544
return errors
545
546
# Usage
547
schema = {"type": "integer", "minimum": 0, "maximum": 100}
548
validator = Draft7Validator(schema)
549
550
report = detailed_error_report(validator, -5)
551
for error in report:
552
print(f"Path: {error['path']}")
553
print(f"Error: {error['message']}")
554
print(f"Invalid value: {error['invalid_value']}")
555
print(f"Rule: {error['validator']} = {error['schema_rule']}")
556
print("---")
557
```
558
559
## Types
560
561
```python { .api }
562
from typing import Any, Callable, Iterable, Iterator, Sequence
563
```