Error Handling and Diagnostics
Relevant source files
The following files were used as context for generating this wiki page:
Error handling and diagnostics in dbt-core are centralized through a structured system of error codes, location tracking, and specialized Jinja exception handlers. The system is designed to provide precise feedback during the parsing, resolution, and execution phases of a dbt project, distinguishing between user configuration errors, database-level failures, and internal system bugs.
Sources: crates/dbt-error/src/codes.rs:11-20, crates/dbt-parser/src/resolver.rs:90-100
Error Classification and Codes
The project uses a structured ErrorCode enumeration to categorize every possible failure state. These codes are 4-digit numbers stored as u16 types and are segmented into ranges based on the source of the error.
Error Code Ranges
| Range | Category | Description |
|---|---|---|
| 0000 – 0999 | Frontend Errors | Originating from the dbt frontend components. |
| 1000 – 8999 | CLI Errors | General user-facing errors related to IO, configuration, and execution. |
| 9000 – 9899 | Internal Errors | System-level failures presented as bugs to the user. |
| 9900 – 9999 | Internal Frontend | Internal failures within the frontend architecture. |
Sources: crates/dbt-error/src/codes.rs:22-315
Specialized CLI Error Segments
CLI errors are further subdivided to allow for granular diagnostics and specific handling logic, such as --warn-error-options.
- Project/Manifest (1150–1199): Failures in loading
dbt_project.yml, resolving packages, or manifest validation. - Network/HTTP (1200–1249): Timeouts, rate limiting, and API errors.
- Adapter/Database (1300–1399): Connection failures, syntax errors, and resource exhaustion.
- Jinja (1500–1599): Macro syntax errors, variable lookups, and type check failures.
Sources: crates/dbt-error/src/codes.rs:160-230
Architecture of Diagnostics
The diagnostics system relies on the FsError type, which wraps an ErrorCode with contextual information including messages and file locations.
This diagram represents the relationship between error codes, the primary error container, and file-based location tracking.
Sources: crates/dbt-error/src/lib.rs, crates/dbt-error/src/codes.rs:16-19
Database Error Detection
The system identifies database-level errors via the is_database_error() method. This is critical for formatting user-friendly messages similar to "Database Error in model X", distinguishing them from general Jinja execution failures.
Sources: crates/dbt-error/src/codes.rs:335-350
Jinja Exception Handling
dbt-core exposes an exceptions object within the Jinja environment to allow project developers to trigger structured errors and warnings directly from macros.
Key Exception Methods
exceptions.warn: Emits a warning log. If the specific error code is configured via--warn-error-options, it upgrades the warning to anExitWithStatuserror.exceptions.raise_compiler_error: Terminates execution with a compilation error, automatically including node metadata (node ID and file path) if available in the current state.exceptions.raise_contract_error: Specifically used when a model's enforced contract fails, generating a detailed Agate table diff between YAML and SQL columns.exceptions.relation_wrong_type: Triggered when attempting to create a relation (e.g., a View) where a different type (e.g., a Table) already exists.
Sources: crates/dbt-jinja-utils/src/functions/base.rs:698-840
Error Propagation Flow
The flow of error reporting from the Jinja environment to the user interface.
Sources: crates/dbt-jinja-utils/src/functions/base.rs:705-725
Resolution Phase Diagnostics
During the resolve phase, the system performs several validation checks to catch configuration issues before execution begins.
Relation Uniqueness
The resolver tracks every relation (Models, Seeds, Snapshots) by its generated alias. If two resources resolve to the same database relation name, an ErrorCode::InvalidConfig is raised, identifying both conflicting unique IDs.
Sources: crates/dbt-parser/src/resolver.rs:610-635
Compute Platform Reachability
A specific diagnostic check ensures that models running on a non-default compute platform (e.g., alt_compute) can reach their upstreams. If an upstream model is purely warehouse-native and not reachable via a catalog, the resolver identifies the specific dependency break.
Sources: crates/dbt-parser/src/resolver.rs:570-605
Formatting and Display
Diagnostic information is formatted for the CLI using specialized formatters that handle duration, outcome, and colorization.
Node Outcome Statuses
The system maps internal execution results to human-readable statuses:
| Outcome | Skip Reason | Display Status |
|---|---|---|
Success | N/A | success / pass |
Skipped | Upstream | skipped |
Skipped | Cached | reused |
Error | N/A | error / fail |
Sources: crates/dbt-common/src/tracing/formatters/node.rs:165-200
Location Reporting
For failures in SQL or YAML files, the diagnostic formatter builds strings in the format path/to/file.sql:line:col. This ensures that for tests and unit tests, the user is directed exactly to the definition that failed validation.
Sources: crates/dbt-common/src/tracing/formatters/node.rs:145-155
Conclusion
Error handling in dbt-core v2 is a multi-layered system that combines static analysis at parse time with dynamic exception handling in Jinja. By utilizing a comprehensive set of error codes and mandatory location tracking, the system provides the "stricter" environment required for performance at scale, ensuring that configuration issues are caught early and reported with high precision.