0
# Exception Classes
1
2
Erdantic defines several exception classes that provide specific error information when operations fail. These exceptions help identify and troubleshoot issues with model analysis, plugin registration, and diagram generation.
3
4
## Exception Hierarchy
5
6
```python { .api }
7
class ErdanticException(Exception):
8
"""Base class for all exceptions from erdantic library."""
9
10
class UnknownModelTypeError(ValueError, ErdanticException):
11
"""Raised when a given model does not match known model types from loaded plugins.
12
13
Attributes:
14
model (type): The model class that was not recognized.
15
available_plugins (list[str]): List of plugin keys that were available.
16
"""
17
18
class PluginNotFoundError(KeyError, ErdanticException):
19
"""Raised when specified plugin key does not match a registered plugin.
20
21
Attributes:
22
key (str): The plugin key that was not found.
23
"""
24
25
class ModelOrModuleNotFoundError(ImportError, ErdanticException):
26
"""Raised when specified fully qualified name of model class or module cannot be imported."""
27
28
class UnresolvableForwardRefError(NameError, ErdanticException):
29
"""Raised when a forward reference in a type annotation cannot be resolved automatically.
30
31
Attributes:
32
name (str): The string representation of the unresolvable forward reference.
33
model_full_name (FullyQualifiedName): The fully qualified name of the model with the forward reference.
34
"""
35
36
class UnevaluatedForwardRefError(ErdanticException):
37
"""Raised when a field's type declaration has an unevaluated forward reference.
38
39
Attributes:
40
model_full_name (FullyQualifiedName): The fully qualified name of the model with the field
41
with the unevaluated forward reference.
42
field_name (str): The name of the field with the unevaluated forward reference.
43
forward_ref (str): The string representation of the unevaluated forward reference.
44
"""
45
46
class FieldNotFoundError(AttributeError, ErdanticException):
47
"""Raised trying to access a field name that does not match any fields returned by the
48
field extractor function for a model.
49
50
Attributes:
51
name (str): The name of the field that was not found.
52
obj (object): The model object that the field was being accessed on.
53
model_full_name (FullyQualifiedName): The fully qualified name of the model.
54
"""
55
```
56
57
## Required Imports
58
59
```python
60
from erdantic.exceptions import (
61
ErdanticException, UnknownModelTypeError, PluginNotFoundError,
62
ModelOrModuleNotFoundError, UnresolvableForwardRefError,
63
UnevaluatedForwardRefError, FieldNotFoundError
64
)
65
from erdantic.core import FullyQualifiedName
66
```
67
68
## Usage Examples
69
70
### Handling Model Type Errors
71
72
```python
73
from erdantic import create
74
from erdantic.exceptions import UnknownModelTypeError
75
76
class MyCustomClass:
77
"""Not a data model class - will cause error."""
78
name: str
79
80
try:
81
diagram = create(MyCustomClass)
82
except UnknownModelTypeError as e:
83
print(f"Model not recognized: {e.model}")
84
print(f"Available plugins: {e.available_plugins}")
85
print("Make sure your class inherits from a supported data model base class")
86
```
87
88
### Handling Plugin Errors
89
90
```python
91
from erdantic.plugins import get_predicate_fn
92
from erdantic.exceptions import PluginNotFoundError
93
94
try:
95
predicate = get_predicate_fn("nonexistent_plugin")
96
except PluginNotFoundError as e:
97
print(f"Plugin '{e.key}' not found")
98
99
# Show available plugins
100
from erdantic import list_plugins
101
print(f"Available plugins: {list_plugins()}")
102
```
103
104
### Handling Import Errors
105
106
```python
107
from erdantic.cli import import_object_from_name
108
from erdantic.exceptions import ModelOrModuleNotFoundError
109
110
try:
111
model_class = import_object_from_name("nonexistent.module.Model")
112
except ModelOrModuleNotFoundError as e:
113
print(f"Could not import: {e}")
114
print("Check that the module path is correct and the module is installed")
115
```
116
117
### Handling Forward Reference Errors
118
119
```python
120
from erdantic import create
121
from erdantic.exceptions import UnresolvableForwardRefError, UnevaluatedForwardRefError
122
123
try:
124
diagram = create(MyModelWithForwardRefs)
125
except UnresolvableForwardRefError as e:
126
print(f"Cannot resolve forward reference '{e.name}' in model {e.model_full_name}")
127
print("Make sure all referenced types are properly imported or defined")
128
except UnevaluatedForwardRefError as e:
129
print(f"Unevaluated forward reference '{e.forward_ref}' in field '{e.field_name}'")
130
print(f"Model: {e.model_full_name}")
131
print("This usually indicates a plugin issue - consider reporting as a bug")
132
```
133
134
### Handling Field Access Errors
135
136
```python
137
from erdantic.core import FieldInfo, FullyQualifiedName
138
from erdantic.exceptions import FieldNotFoundError
139
140
# This would occur when accessing field information programmatically
141
try:
142
# Simulate field access that fails
143
field_info = FieldInfo(
144
model_full_name=FullyQualifiedName.from_object(MyModel),
145
name="nonexistent_field",
146
type_name="str"
147
)
148
raw_type = field_info.raw_type # This accesses the field
149
except FieldNotFoundError as e:
150
print(f"Field '{e.name}' not found on model {e.model_full_name}")
151
print("Check that the field name is correct")
152
```
153
154
### Comprehensive Error Handling
155
156
```python
157
from erdantic import draw
158
from erdantic.exceptions import (
159
ErdanticException, UnknownModelTypeError, PluginNotFoundError,
160
ModelOrModuleNotFoundError, UnresolvableForwardRefError,
161
UnevaluatedForwardRefError, FieldNotFoundError
162
)
163
164
def safe_draw_diagram(models_or_modules, output_path):
165
"""Draw diagram with comprehensive error handling."""
166
try:
167
draw(*models_or_modules, out=output_path)
168
print(f"Diagram successfully created: {output_path}")
169
170
except UnknownModelTypeError as e:
171
print(f"❌ Unknown model type: {e.model.__name__}")
172
print(f" Available plugins: {e.available_plugins}")
173
return False
174
175
except PluginNotFoundError as e:
176
print(f"❌ Plugin not found: {e.key}")
177
return False
178
179
except ModelOrModuleNotFoundError as e:
180
print(f"❌ Import error: {e}")
181
return False
182
183
except (UnresolvableForwardRefError, UnevaluatedForwardRefError) as e:
184
print(f"❌ Forward reference error: {e}")
185
return False
186
187
except FieldNotFoundError as e:
188
print(f"❌ Field access error: {e}")
189
return False
190
191
except ErdanticException as e:
192
print(f"❌ Erdantic error: {type(e).__name__}: {e}")
193
return False
194
195
except Exception as e:
196
print(f"❌ Unexpected error: {type(e).__name__}: {e}")
197
return False
198
199
return True
200
201
# Usage
202
success = safe_draw_diagram([MyModel1, MyModel2], "diagram.png")
203
if not success:
204
print("See error messages above for troubleshooting guidance")
205
```
206
207
### Error Recovery Strategies
208
209
```python
210
from erdantic import create, list_plugins
211
from erdantic.exceptions import UnknownModelTypeError, PluginNotFoundError
212
213
def create_diagram_with_fallback(models):
214
"""Create diagram with fallback strategies for common errors."""
215
216
# Strategy 1: Try creating diagram normally
217
try:
218
return create(*models)
219
except UnknownModelTypeError as e:
220
print(f"Model {e.model} not supported by current plugins")
221
222
# Strategy 2: Check if we need additional plugins
223
available = e.available_plugins
224
if "attrs" not in available:
225
print("Consider installing: pip install attrs")
226
if "msgspec" not in available:
227
print("Consider installing: pip install msgspec")
228
229
# Strategy 3: Filter to only supported models
230
supported_models = []
231
for model in models:
232
try:
233
create(model) # Test individual model
234
supported_models.append(model)
235
except UnknownModelTypeError:
236
print(f"Skipping unsupported model: {model.__name__}")
237
238
if supported_models:
239
print(f"Creating diagram with {len(supported_models)} supported models")
240
return create(*supported_models)
241
else:
242
print("No supported models found")
243
return None
244
245
# Usage
246
diagram = create_diagram_with_fallback([Model1, Model2, UnsupportedModel])
247
if diagram:
248
diagram.draw("filtered_diagram.png")
249
```
250
251
## Common Error Scenarios
252
253
### Plugin Installation Issues
254
255
When erdantic cannot find support for your model types:
256
257
```python
258
# Error: UnknownModelTypeError with attrs model
259
# Solution: pip install attrs
260
261
# Error: UnknownModelTypeError with msgspec model
262
# Solution: pip install msgspec
263
264
# Error: All models show as unsupported
265
# Solution: Check that models inherit from proper base classes
266
```
267
268
### Forward Reference Issues
269
270
When models contain forward references that cannot be resolved:
271
272
```python
273
# Common causes:
274
# 1. Missing __future__ import: from __future__ import annotations
275
# 2. Circular imports between modules
276
# 3. Type hints referencing classes not yet defined
277
# 4. Missing imports for referenced types
278
279
# Solutions:
280
# 1. Add proper imports
281
# 2. Restructure to avoid circular dependencies
282
# 3. Use string literals for forward references
283
# 4. Ensure all referenced types are accessible
284
```
285
286
### CLI Import Issues
287
288
When using the CLI with module or class paths:
289
290
```python
291
# Error: ModelOrModuleNotFoundError
292
# Common causes:
293
# 1. Typo in module/class path
294
# 2. Module not installed or not in PYTHONPATH
295
# 3. Class doesn't exist in specified module
296
297
# Solutions:
298
# 1. Verify spelling and case sensitivity
299
# 2. Check module installation: python -c "import mymodule"
300
# 3. Check class exists: python -c "from mymodule import MyClass"
301
```