π¨ Proper Error Handling in dbt Custom Materializations with raise_database_error
In dbt, when writing custom materializations, itβs important to handle errors gracefully and consistently. Instead of allowing Python or Jinja errors to crash silently or give cryptic messages, dbt provides a native mechanism:
β
raise_database_error(msg)
This built-in dbt function:
- Halts execution with a clear, user-defined error,
- Logs it through dbtβs native system,
- Maintains a full stack trace,
- Makes your custom materialization easier to debug and maintain.
π§± Example: Custom Materialization with Error Handling
Letβs create a custom materialization called safe_table
that:
- Builds a table normally,
- But raises a helpful error if the
unique_key
config is missing.
π File: macros/materializations/safe_table.sql
{% materialization safe_table, default %}
{% set target_relation = api.Relation.create(
identifier=model['alias'],
schema=model['schema'],
database=model['database']
) %}
{% set unique_key = config.get('unique_key') %}
{% if not unique_key %}
{{ exceptions.raise_database_error(
"The 'unique_key' config is required for the 'safe_table' materialization."
) }}
{% endif %}
-- If no error, proceed with standard table creation
{% do run_query("drop table if exists " ~ target_relation) %}
{% do run_query("create table " ~ target_relation ~ " as (select * from " ~ this) %}
{{ return({'relations': [target_relation]}) }}
{% endmaterialization %}
β How It Works
- If the user forgets to set
unique_key
in their model:{{ config(materialized='safe_table') }}
dbt will raise:Database Error in model my_model (models/my_model.sql) The 'unique_key' config is required for the 'safe_table' materialization.
- This error:
- Is clean and specific,
- Shows up in
dbt run
output and logs, - Makes it easy to fix the issue.
π― Why Use raise_database_error()
?
Feature | Benefit |
---|---|
β Integrated stack trace | Better debugging in CI and local runs |
β Clean log output | Shows up in dbt Cloud and CLI logs |
β Stops execution safely | Avoids partial state or silent failures |
β Easy to test | Trigger and assert error conditions in CI |
π Bonus Tip: Use raise_compiler_error()
for compile-time issues
- Use
raise_database_error()
for runtime errors (e.g., SQL execution problems). - Use
raise_compiler_error()
for compile-time issues (e.g., bad configs, missing variables).