0
# Exception Handling
1
2
dbt-core provides a comprehensive exception hierarchy for structured error handling and reporting. Most exceptions inherit from the dbt-common exception system and include error codes, structured messaging, and context information.
3
4
## Core Exception Classes
5
6
### dbt-core Specific Exceptions
7
8
```python { .api }
9
class ContractBreakingChangeError(DbtRuntimeError):
10
"""
11
Breaking change to an enforced contract.
12
13
Raised when dbt detects changes that break enforced model contracts
14
during state comparison.
15
"""
16
17
CODE = 10016
18
MESSAGE = "Breaking Change to Contract"
19
20
def __init__(
21
self,
22
breaking_changes: List[str],
23
node=None,
24
) -> None:
25
"""
26
Initialize contract breaking change error.
27
28
Args:
29
breaking_changes: List of specific breaking changes detected
30
node: Node where the breaking change occurred (optional)
31
"""
32
33
@property
34
def type(self):
35
"""Error type description."""
36
return "Breaking change to contract"
37
38
def message(self):
39
"""Formatted error message with breaking change details."""
40
```
41
42
### dbt-common Base Exceptions
43
44
These exceptions are imported from dbt-common and form the foundation of dbt's error system:
45
46
```python { .api }
47
class DbtInternalError(Exception):
48
"""
49
Internal dbt errors indicating bugs or unexpected conditions.
50
51
These represent errors in dbt's logic rather than user configuration
52
or data issues.
53
"""
54
55
class DbtRuntimeError(Exception):
56
"""
57
Runtime execution errors during dbt operations.
58
59
These occur during execution and typically indicate issues with
60
SQL execution, database connectivity, or data processing.
61
"""
62
63
class DbtConfigError(Exception):
64
"""
65
Configuration-related errors.
66
67
Raised when there are issues with project configuration, profiles,
68
or other configuration files.
69
"""
70
71
class DbtValidationError(Exception):
72
"""
73
Data validation errors.
74
75
Raised when data doesn't meet expected validation criteria or
76
schema requirements.
77
"""
78
79
class CompilationError(Exception):
80
"""
81
SQL compilation errors.
82
83
Raised when dbt cannot compile models, macros, or other SQL
84
into valid executable statements.
85
"""
86
87
class CommandResultError(Exception):
88
"""
89
Command execution errors.
90
91
Raised when external commands or operations fail during
92
dbt execution.
93
"""
94
```
95
96
## CLI-Specific Exceptions
97
98
### dbt.cli.exceptions
99
100
```python { .api }
101
class DbtUsageException(Exception):
102
"""
103
CLI usage errors.
104
105
Raised when command-line arguments are invalid or when
106
CLI commands are used incorrectly.
107
"""
108
109
class DbtInternalException(Exception):
110
"""
111
Internal CLI errors.
112
113
Raised for unexpected internal errors in the CLI layer.
114
"""
115
```
116
117
## Exception Properties
118
119
Most dbt exceptions include structured information:
120
121
### Error Codes
122
123
```python
124
# Each exception type has a unique error code
125
exception.CODE # Integer error code for programmatic handling
126
```
127
128
### Error Messages
129
130
```python
131
# Structured error messages
132
exception.MESSAGE # Base message template
133
exception.message() # Formatted message with context
134
str(exception) # String representation
135
```
136
137
### Context Information
138
139
```python
140
# Many exceptions include context about where the error occurred
141
exception.node # dbt node where error occurred (if applicable)
142
exception.type # Error type description
143
```
144
145
## Usage Patterns
146
147
### Basic Exception Handling
148
149
```python
150
from dbt.cli.main import dbtRunner
151
from dbt.exceptions import (
152
DbtRuntimeError,
153
CompilationError,
154
DbtConfigError
155
)
156
157
runner = dbtRunner()
158
159
try:
160
result = runner.invoke(['run'])
161
if not result.success:
162
raise result.exception
163
except CompilationError as e:
164
print(f"Compilation failed: {e}")
165
# Handle SQL compilation issues
166
except DbtConfigError as e:
167
print(f"Configuration error: {e}")
168
# Handle configuration problems
169
except DbtRuntimeError as e:
170
print(f"Runtime error: {e}")
171
# Handle execution issues
172
```
173
174
### CLI Exception Handling
175
176
```python
177
from dbt.cli.exceptions import DbtUsageException, DbtInternalException
178
from click.exceptions import ClickException
179
180
try:
181
result = runner.invoke(['run', '--invalid-flag'])
182
except DbtUsageException as e:
183
print(f"Usage error: {e}")
184
# Handle invalid CLI usage
185
except DbtInternalException as e:
186
print(f"Internal CLI error: {e}")
187
# Handle internal CLI issues
188
except ClickException as e:
189
print(f"Click error: {e}")
190
# Handle Click framework errors
191
```
192
193
### Contract Validation
194
195
```python
196
from dbt.exceptions import ContractBreakingChangeError
197
198
try:
199
result = runner.invoke(['run', '--select', 'state:modified'])
200
except ContractBreakingChangeError as e:
201
print(f"Contract validation failed:")
202
print(f"Error type: {e.type}")
203
for change in e.breaking_changes:
204
print(f" - {change}")
205
206
# Access error details
207
print(f"Error code: {e.CODE}")
208
print(f"Node: {e.node}")
209
```
210
211
### Error Code Handling
212
213
```python
214
def handle_dbt_error(exception):
215
"""Handle dbt errors based on error codes."""
216
if hasattr(exception, 'CODE'):
217
code = exception.CODE
218
219
if code == 10016: # ContractBreakingChangeError
220
print("Handle contract breaking change")
221
elif code in [1001, 1002]: # Compilation errors
222
print("Handle compilation issues")
223
else:
224
print(f"Handle error code {code}")
225
else:
226
print("Handle generic error")
227
228
try:
229
result = runner.invoke(['compile'])
230
except Exception as e:
231
handle_dbt_error(e)
232
```
233
234
### Logging Errors
235
236
```python
237
import logging
238
from dbt.exceptions import DbtRuntimeError
239
240
logger = logging.getLogger(__name__)
241
242
try:
243
result = runner.invoke(['test'])
244
except DbtRuntimeError as e:
245
# Log structured error information
246
logger.error(
247
"dbt test failed",
248
extra={
249
'error_code': getattr(e, 'CODE', None),
250
'error_type': getattr(e, 'type', type(e).__name__),
251
'node': getattr(e, 'node', None),
252
'message': str(e)
253
}
254
)
255
raise
256
```
257
258
## Error Categories
259
260
### Configuration Errors
261
262
- Invalid dbt_project.yml syntax
263
- Missing or invalid profiles.yml
264
- Invalid package specifications
265
- Schema validation failures
266
267
```python
268
from dbt.exceptions import DbtConfigError
269
270
try:
271
runner.invoke(['parse'])
272
except DbtConfigError as e:
273
print("Fix configuration issues")
274
```
275
276
### Compilation Errors
277
278
- Invalid Jinja syntax in models
279
- Undefined macros or variables
280
- Circular dependencies
281
- Invalid SQL syntax
282
283
```python
284
from dbt.exceptions import CompilationError
285
286
try:
287
runner.invoke(['compile'])
288
except CompilationError as e:
289
print("Fix SQL or Jinja issues")
290
```
291
292
### Runtime Errors
293
294
- Database connection failures
295
- SQL execution errors
296
- Permission issues
297
- Resource conflicts
298
299
```python
300
from dbt.exceptions import DbtRuntimeError
301
302
try:
303
runner.invoke(['run'])
304
except DbtRuntimeError as e:
305
print("Fix runtime execution issues")
306
```
307
308
### Validation Errors
309
310
- Schema test failures
311
- Data quality check failures
312
- Contract validation failures
313
314
```python
315
from dbt.exceptions import DbtValidationError, ContractBreakingChangeError
316
317
try:
318
runner.invoke(['test'])
319
except ContractBreakingChangeError as e:
320
print("Contract validation failed")
321
except DbtValidationError as e:
322
print("Data validation failed")
323
```
324
325
## Integration with External Systems
326
327
### Airflow Integration
328
329
```python
330
from airflow.exceptions import AirflowException
331
from dbt.exceptions import DbtRuntimeError
332
333
def airflow_dbt_task():
334
try:
335
result = runner.invoke(['run'])
336
if not result.success:
337
raise AirflowException(f"dbt failed: {result.exception}")
338
except DbtRuntimeError as e:
339
# Convert to Airflow exception
340
raise AirflowException(f"dbt runtime error: {e}")
341
```
342
343
### Custom Error Handling
344
345
```python
346
class CustomDbtError(Exception):
347
"""Custom exception for application-specific dbt errors."""
348
349
def __init__(self, original_error, context=None):
350
self.original_error = original_error
351
self.context = context or {}
352
super().__init__(str(original_error))
353
354
def run_with_custom_handling():
355
try:
356
result = runner.invoke(['run'])
357
except Exception as e:
358
raise CustomDbtError(
359
e,
360
context={'operation': 'run', 'timestamp': time.time()}
361
)
362
```