CertSafari
    DBT Analytics Engineering· Lessons

    Domain 3 · Lesson 18/31

    Reading dbt error messages and logs

    Understanding logged error messages

    15 min read
    3.23% of exam
    6 sources
    Published 12 Oct 2026
    Docs as of 12 Oct 2026

    What you will be able to do

    • Name the error type dbt reports for each stage of a run, and say what each type means about where the fault is
    • Read the file location in an error message and go straight to the file that caused it
    • Tell a dbt-side Compilation Error apart from a Database Error that the warehouse sends back
    • Find what really happened in logs/dbt.log, and tune what goes to the terminal and the log file with log-level, debug and quiet flags
    • Read dbt's exit codes 0, 1 and 2 in scripts and CI

    Key concept

    Error type as a pointer to the failing stage — Each dbt error names its type and the file it came from. The type tells you which stage of the run failed: Runtime for initialization, Compilation for parsing, Dependency for graph validation, Database for SQL execution. That tells you whether to look at your setup, your Jinja and YAML, your refs, or your SQL.

    1.What a dbt error message tells you

    A failed dbt command does not print a random stack trace. The error message almost always has two parts. The first is the error type, such as Runtime Error, Compilation Error or Database Error. The second is the file where the problem happened. Start debugging from those two facts: open the file it names, look for a quick fix, and only then widen the search.

    The error type matters because dbt works in stages. Commands like dbt run first check that you're in a dbt project and can connect. Next dbt parses your Jinja and YAML, then builds and checks the dependency graph, and only after that sends SQL to the warehouse. Each stage raises its own type of error. So the type tells you how far dbt got before it stopped.

    The stages of a dbt run and the error type each one raises
    StepWhat dbt checksError type
    InitializeThat this is a dbt project, and that dbt can connect to the warehouseRuntime Error
    ParsingThat Jinja snippets in .sql files are valid, and that .yml files are validCompilation Error
    Graph validationCompiles dependencies into a graph and checks that it is acyclicDependency Error
    SQL executionRuns the modelsDatabase Error

    Here is a full failure summary from the terminal. The first line names the type and the model, with its path in brackets. The next line is the warehouse's own message, and the line after that says where the compiled SQL was written. The Done. line counts the outcomes. A single error here also means anything downstream of customers was skipped, which is why one broken model can turn a whole run red.

    End of a failed dbt run: error type, model, file path, warehouse message and compiled SQL locationtext
    Completed with 1 error and 0 warnings:
    
    Database Error in model customers (models/customers.sql)
      Syntax error: Expected ")" but got identifier `your-info-12345` at [13:15]
      compiled SQL at target/run/jaffle_shop/customers.sql
    
    Done. PASS=0 WARN=0 ERROR=1 SKIP=0 TOTAL=1

    Checkpoint 1 of 9· Match them up

    Match each error type to the stage of a dbt run that raises it

    Tap a term, then the definition that fits it.

    Checkpoint 2 of 9· Exam question

    A teammate's pull request fails during dbt's parsing step with this error: Compilation Error - Invalid models config given in models/staging/schema.yml Additional properties are not allowed ('materialize' was unexpected) models: - name: stg_orders materialize: table columns: - name: order_id data_tests: - unique Which line is causing this specific error, and why?

    Sources12

    2.Runtime and Dependency errors: before any SQL runs

    A Runtime Error means dbt never got as far as your models. The cause is your environment, not your code. The clearest example is running dbt from the wrong folder:

    Runtime Error when dbt cannot find dbt_project.ymltext
    Running with dbt=1.7.1
    Encountered an error:
    Runtime Error
      fatal: Not a dbt project (or any of the parent directories). Missing dbt_project.yml file

    The fix is to use pwd and cd until you're in the folder that holds dbt_project.yml. Other Runtime Errors come from the connection setup. Could not find profile named 'jaffle_shops' means the profile: key in dbt_project.yml doesn't match any top-level name in profiles.yml. A single letter is enough: jaffle_shops against jaffle_shop. A bad password shows as a Runtime Error with a Database Error nested inside it, because the warehouse refused the connection while dbt was listing schemas. In both cases dbt debug --config-dir shows where profiles.yml lives. After a fix, dbt debug confirms that profiles.yml, dbt_project.yml and the connection test all pass.

    A Dependency Error happens one stage later. dbt has parsed every file but can't order the models, because the refs form a loop. The message spells the loop out, as in Found a cycle: model.jaffle_shop.customers --> model.jaffle_shop.stg_customers --> model.jaffle_shop.customers. You fix it by changing the ref calls so the loop breaks. If a model needs to refer to itself, use {{ this }} rather than a ref to its own name. Laying out a DAG so this can't happen is covered in [building clean DAGs](lesson:1.5).

    Checkpoint 3 of 9· Check yourself

    dbt run fails with Runtime Error ... Could not find profile named 'jaffle_shops'. The models compiled fine yesterday on a colleague's machine. What do you check first?

    Sources1

    3.Compilation Error or Database Error: is it dbt or the SQL?

    The most useful thing an error type tells you is which side the fault is on: dbt's or the warehouse's. A Compilation Error is raised by dbt itself, before any SQL leaves your machine. A bad ref is one cause. Broken Jinja is another. In that case dbt hands on the message from the Jinja library, along with the file where it happened:

    Compilation Error from a ref to a model that does not existtext
    $ dbt run -s customers
    Running with dbt=1.1.0
    
    Encountered an error:
    Compilation Error in model customers (models/customers.sql)
      Model 'model.jaffle_shop.customers' (models/customers.sql) depends on a node named 'stg_customer' which was not found
    Compilation Error from a macro missing its closing tagtext
    $ dbt run
    Running with dbt=1.7.1
    Compilation Error in macro (macros/cents_to_dollars.sql)
      Reached EOF without finding a close tag for macro (searched from line 1)

    That EOF message comes from a missing {% endmacro %}. The same kind of error appears if you forget a closing }, or close a for loop before the if inside it. Invalid YAML and unknown keys in properties files are also Compilation Errors, because dbt reads .yml files during parsing. Reading those messages has its own lesson: [troubleshooting .yml compilation errors](lesson:3.3).

    A Database Error works the other way round. dbt rendered your model and sent the SQL, and the warehouse rejected it. The message, like 001003 (42000): SQL compilation error, is the warehouse's own text, so its documentation may be what explains it. Don't be fooled by the word "compilation" here: this is the warehouse compiling SQL, not dbt compiling Jinja. Most of the time the fault is in the SQL of the model the error names. The error line compiled SQL at target/run/... points to the exact statement dbt ran. Opening that file next to the model is the method taught in [troubleshooting with compiled code](lesson:3.2).

    Checkpoint 4 of 9· Check yourself

    A run ends with Database Error in model customers (models/customers.sql) followed by 001003 (42000): SQL compilation error: syntax error line 14 at position 4 unexpected 'from'. What does this tell you?

    Checkpoint 5 of 9· Exam question

    A `dbt run` on `models/marts/finance/revenue.sql` fails with: Database Error in model revenue (models/marts/finance/revenue.sql) 001003 (42000): SQL compilation error: syntax error line 14 at position 4 unexpected 'from'. compiled SQL at target/run/jaffle_shop/models/marts/finance/revenue.sql The `.sql` file itself looks syntactically fine at line 14. What should the analytics engineer do next to isolate whether the bug is in the source SQL or in dbt's Jinja rendering?

    Sources1

    4.logs/dbt.log: the full record of a run

    dbt writes every event to two places at once. The terminal (stdout) gets short, live progress lines. logs/dbt.log gets far more. The text log file holds every DEBUG-level event, with the log level and thread name on each line. It also holds every query dbt ran, not just the one that failed. The newest errors are at the bottom of the file. By default logs/ sits next to dbt_project.yml, and the --log-path flag moves it.

    Lines from logs/dbt.log: timestamp, level, thread, then the messagetext
    21:21:16.190990 [debug] [MainThread]: Partial parsing enabled: 0 files deleted, 0 files added, 0 files changed.
    21:21:16.191404 [debug] [MainThread]: Partial parsing enabled, no changes found, skipping parsing
    21:21:16.207330 [info ] [MainThread]: Found 2 models, 0 tests, 0 snapshots, 1 analysis, 535 macros, 0 operations, 1 seed file, 0 sources, 0 exposures, 0 metrics, 0 groups

    The log matters most when a Database Error comes from SQL that isn't in any model file. dbt also runs queries of its own: introspective queries that list objects, create schema statements, pre-hooks, post-hooks, on-run-start and on-run-end hooks, and the merge, update and insert statements behind incremental models and snapshots. You won't see that SQL by reading your model, so the log is where to find it. In the dbt platform, the same detail is under Details for a model in the command output. For a failed job, expand the run steps in Run History to see the console and debug logs.

    A busy log is hard to read, so cut it down to one failure. Empty the file, run dbt again for the one model that fails, and the log holds only that run.

    Checkpoint 6 of 9· Put it in order

    A strange Database Error keeps showing up and the log is thousands of lines long. Put these steps in order to isolate it.

    1. 1.Re-execute dbt run for just the problematic model
    2. 2.Open logs/dbt.log and delete its contents
    3. 3.Read the log, which now holds only the queries from that one run

    Checkpoint 7 of 9· Exam question

    A `dbt run` fails before executing any SQL with: Found a cycle: model.jaffle_shop.customers --> model.jaffle_shop.stg_customers --> model.jaffle_shop.customers Which of the following changes would resolve this circular dependency? (Select all that apply)(Select 2)

    Sources314

    5.Controlling log output and reading exit codes

    You can choose how much detail reaches each destination. --log-level sets the lowest severity written to both the terminal and the log file. The levels are debug, info, warn, error and none. --log-level-file sets the file on its own, so --log-level-file none stops writing the file but keeps terminal output. --debug (or -d) prints debug-level lines in the terminal too. That's useful when you can't easily open the file, such as in a CI log, but the output is long. --quiet (-q) goes the other way and shows only errors. Anything passed to the print() macro still appears, which makes --quiet handy when you're tracking down a Jinja bug with print() calls.

    Flags that change what dbt logs, and where
    FlagEffect
    --log-level debugMinimum severity for both console and file logs
    --log-level-file errorSets the file log level separately from the console
    --debug / -dSends debug-level logs to stdout as well as logs/dbt.log
    --quiet / -qShows only error logs in stdout, plus print() output
    --log-format jsonFully structured JSON log lines instead of text
    --log-pathMoves the logs directory from its default location

    Log format is a separate setting from log level. --log-format takes text, json or default and applies to both the terminal and the file. --log-format-file sets the file on its own. The otel format streams OpenTelemetry-style telemetry to the console only, and setting --log-format-file otel does nothing.

    Checkpoint 8 of 9· Fill the gap

    You want debug-level events shown in the terminal as structured JSON so a CI tool can parse them. Which flag completes the command?

    dbt build  ?  --log-format json

    Scripts and orchestrators often skip the log and look only at the exit code. 0 means the command finished with no errors. 1 means dbt finished but hit at least one handled error, such as a model syntax error or bad permissions. Some models may have been skipped. 2 means something unhandled stopped dbt partway, such as a ctrl-c or a network interruption. Any exit code other than zero means failure, so a CI step should treat 1 and 2 both as failures. Only 2 hints that the run itself was cut short.

    Checkpoint 9 of 9· Check yourself

    A nightly dbt build exits with code 1. What do you know before opening any logs?

    Sources56

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.A Database Error that says "SQL compilation error" means dbt failed to compile the model's Jinja.Why is that wrong?

      Database Errors come from the warehouse, and dbt passes them on unchanged. The "compilation" in the message is the warehouse's, and the fault is usually in the model's SQL. Jinja problems in dbt are raised as Compilation Errors.

      Covered in Compilation Error or Database Error: is it dbt or the SQL?

    2. 2.The latest failure is at the top of logs/dbt.log.Why is that wrong?

      dbt adds new entries to the end of the log, so the newest errors are at the bottom.

      Covered in logs/dbt.log: the full record of a run

    3. 3.Exit code 2 is just a more serious version of exit code 1, such as several failed models instead of one.Why is that wrong?

      Exit code 1 means handled errors in a run that finished. Exit code 2 means an unhandled interruption, such as ctrl-c or a network drop, however many models failed.

      Covered in Controlling log output and reading exit codes

    4. 4.--quiet hides everything except errors, including output from print() calls you added to debug a macro.Why is that wrong?

      --quiet hides non-error logs, but anything passed to the print() macro still shows in the output.

      Covered in Controlling log output and reading exit codes

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “will normally contain the type of error (more on these error types below), and the file where the error occurred”
      ↩︎ What a dbt error message tells you
      “Check that this a dbt project, and that dbt can connect to the warehouse”
      ↩︎ What a dbt error message tells you
      “Use pwd to check that you're in the right directory.”
      ↩︎ Runtime and Dependency errors: before any SQL runs
      “After updating the credentials, run dbt debug to check you can connect”
      ↩︎ Runtime and Dependency errors: before any SQL runs
      “If you need to reference the current model, use the {{ this }} variable instead.”
      ↩︎ Runtime and Dependency errors: before any SQL runs
      “Here, we rely on the Jinja library to pass back an error, and then just pass it on to you.”
      ↩︎ Compilation Error or Database Error: is it dbt or the SQL?
      “These errors come from your data warehouse, and dbt passes the message on.”
      ↩︎ Compilation Error or Database Error: is it dbt or the SQL?
      “90% of the time, there's a mistake in the SQL of your model.”
      ↩︎ Compilation Error or Database Error: is it dbt or the SQL?
      “In these cases, you should check out the logs — this contains all the queries dbt has run.”
      ↩︎ logs/dbt.log: the full record of a run
      “will normally contain the type of error (more on these error types below), and the file where the error occurred”
      ↩︎ Key concept
      “These errors come from your data warehouse, and dbt passes the message on.”
      ↩︎ Exam trap 1
      “Recent errors will be at the bottom of the file.”
      ↩︎ Exam trap 2
      “Compile the dependencies into a graph. Check that it's acyclic.”
      ↩︎ Checkpoint
      “Check the profile: key in your dbt_project.yml.”
      ↩︎ Checkpoint
      “depends on a node named 'stg_customer' which was not found”
      ↩︎ Prediction
      “clean out your logs by opening the file, and deleting the contents. Then, re-execute dbt run for just the problematic model.”
      ↩︎ Checkpoint
    2. 2.
      “Any models downstream of this model will also be skipped.”
      ↩︎ What a dbt error message tells you
    3. 3.
      “The text-formatted log messages in this file include all DEBUG-level events, as well as contextual information, such as log level and thread name.”
      ↩︎ logs/dbt.log: the full record of a run
      “The location of this file can be configured via the log-path flag.”
      ↩︎ logs/dbt.log: the full record of a run
    4. 4.
      “expand the run steps to view console and debug logs to review the detailed log messages.”
      ↩︎ logs/dbt.log: the full record of a run
    5. 5.
      “The available options for the log levels are debug, info, warn, error, or none.”
      ↩︎ Controlling log output and reading exit codes
      “This has the effect of showing debug-level log information in the terminal in addition to the logs/dbt.log file.”
      ↩︎ Controlling log output and reading exit codes
      “You can use the QUIET config to show only error logs in stdout.”
      ↩︎ Controlling log output and reading exit codes
      “Setting --log-format-file otel has no effect.”
      ↩︎ Controlling log output and reading exit codes
      “Logs will still include the output of anything passed to the print() macro.”
      ↩︎ Exam trap 4
    6. 6.
      “a zero exit code will always imply success whereas a nonzero exit code will always imply failure.”
      ↩︎ Controlling log output and reading exit codes
      “The dbt invocation completed with an unhandled error (eg. ctrl-c, network interruption, etc).”
      ↩︎ Exam trap 3
      “The run was completed, but some models may have been skipped.”
      ↩︎ Checkpoint

    Ready to test yourself?

    Practise the 11 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.