CertSafari
    DBT Analytics Engineering· Lessons

    Domain 3 · Lesson 19/31

    Troubleshooting dbt models with compiled SQL

    Troubleshooting using compiled code

    14 min read
    3.23% of exam
    8 sources
    Published 12 Oct 2026
    Docs as of 12 Oct 2026

    What you will be able to do

    • Tell apart target/compiled, target/run and logs/dbt.log, and know which one to open for a given failure
    • Use dbt compile (with --select or --inline) and dbt show to see the SQL a model or a Jinja snippet really produces
    • Decide whether a failure is a plain SQL mistake or a Jinja/macro problem by comparing the model file with its compiled SQL
    • Find the SQL behind failing tests and behind queries dbt runs on its own, such as merges and hooks

    Key concept

    Compiled SQL — Compiled SQL is your model after dbt has rendered every ref, macro and Jinja expression into plain SQL that the warehouse can run. When a model fails, the compiled SQL is what the warehouse actually received, so you debug that version and not the Jinja you wrote.

    1.Where dbt writes the SQL it runs

    The warehouse never sees the .sql file you wrote. It sees what dbt produces after rendering every {{ ref() }}, macro call and {% if %} block. Once a model mixes Jinja into its SQL, your source file and the query that ran are two different texts. Most hard bugs live in the gap between them. dbt writes the rendered text to disk, and learning where it goes is the first troubleshooting skill.

    The CLI writes to three places, and each holds a different artifact. target/compiled/ holds the bare select statement for each model, and you can paste it into any query editor. target/run/ holds the statement dbt actually executed to build the model, meaning the select wrapped in the create statement for its materialization. logs/dbt.log records every query dbt ran plus extra logging, and the newest errors are at the bottom. In the dbt platform you get the same information by clicking a model in the run output and opening Details.

    Three places to look for the SQL behind a dbt run (CLI)
    LocationWhat it containsOpen it when
    target/compiled/Compiled select statements you can run in any query editorYou want to see what your Jinja and macros rendered to, or run the model's query by hand
    target/run/The SQL dbt executes to build your models (compiled create statements)A Database Error points you here, and you want the exact statement the warehouse rejected
    logs/dbt.logAll the queries dbt runs, plus additional logging; recent errors at the bottomThe failing SQL is not your model's select, for example a hook or an incremental merge

    Checkpoint 1 of 8· Match them up

    Match each location to what you will find there.

    Tap a term, then the definition that fits it.

    Checkpoint 2 of 8· Exam question

    Which two statements correctly distinguish `target/compiled/` from `target/run/` when troubleshooting a failing model?(Select 2)

    Sources1

    2.Producing compiled SQL on demand

    You don't have to run a model and wait for it to fail before you can read its compiled SQL. dbt compile renders models, data tests, analyses and other resources into the target/ directory without materializing anything. It exists for two debugging jobs: looking at what complex Jinja or macro logic produced, and running a model's or test's underlying select by hand to find a bug.

    For one node, or for a snippet you're unsure about, compile can be interactive. --select names a single node, and --inline takes an arbitrary piece of dbt-SQL. In both cases dbt prints the compiled SQL to the terminal and also writes it to target/. The --inline form is the quickest way to see what a ref resolves to: select * from {{ ref('raw_orders') }} comes back as select * from "jaffle_shop"."main"."raw_orders".

    Compiling one model, and compiling an inline Jinja snippetbash
    dbt compile --select "stg_orders"
    dbt compile --inline "select * from {{ ref('raw_orders') }}"

    Compile and parse do different jobs. dbt parse reads and validates the project without a warehouse connection. The manifest it writes has no compiled SQL in it. dbt compile does need a connection, because many models can only be rendered after introspective queries run, such as filling the relation cache or resolving a macro like run_query or dbt_utils.get_column_values. As a result, compiled SQL for those resources can differ depending on the state of warehouse metadata at the moment you compile. Compiling is also never a required step before a build: dbt run and the other building commands compile on their own.

    dbt show goes one step further than compile. It compiles a single model, test, analysis or --inline query, runs it, and prints the first five rows in the terminal. Nothing gets materialized. Use --limit n to change the row count, which also adds a SQL limit so the warehouse only processes that many rows. Use compile when you need the SQL text and show when you need the data that SQL returns. Like the other commands in [dbt's command set](lesson:1.4), show selects only one node.

    Checkpoint 3 of 8· Check yourself

    A teammate wants compiled SQL for every model in a project, and plans to run dbt parse on a laptop with no warehouse access and then read the manifest. What actually happens?

    Checkpoint 4 of 8· Exam question

    An analytics engineer runs `dbt run` and sees: `Compilation Error in macro (macros/cents_to_dollars.sql) Reached EOF without finding a close tag for macro (searched from line 1)`. What is the most likely root cause, and what should they check first in the compiled output?

    Sources23

    3.Is it your SQL or your Jinja?

    A Database Error means the warehouse rejected a query, and dbt passes the warehouse's message along. [Reading that message](lesson:3.1) tells you which model failed. It also gives a path, and that path points to compiled SQL, not to your model file. The line and position numbers in the error count lines in the compiled file. If your model has a long Jinja loop, "line 14" in the compiled file may be nowhere near line 14 of what you wrote.

    A warehouse error, with dbt pointing at the compiled SQLtext
    Database Error in model customers (models/customers.sql)
      001003 (42000): SQL compilation error:
      syntax error line 14 at position 4 unexpected 'from'.
      compiled SQL at target/run/jaffle_shop/models/customers.sql

    Most of these failures are plain SQL mistakes in the model. To find them, open the model and its compiled SQL side by side and re-run the query by itself. On the CLI, paste the compiled query into a query runner such as the Snowflake UI. In the dbt platform, use the Preview button on the model. Once the isolated query runs cleanly, fix the model and rerun the failed model. Any models downstream of the failure were skipped, so they need to run again too. Testing that fix before merging is covered in [fix-then-test](lesson:3.4).

    Checkpoint 5 of 8· Put it in order

    A model fails with a Database Error. Put the troubleshooting steps in order.

    1. 1.Fix the mistake
    2. 2.Open the model file and its compiled SQL side by side
    3. 3.Re-execute the compiled query on its own to isolate the error
    4. 4.Rerun the failed model

    The side-by-side comparison also catches the other kind of bug: SQL that dbt generated wrongly. If the compiled text doesn't match what you meant to write, the problem is in the Jinja. You might see a missing column, an empty where, or a loop that produced one branch too many. Jinja bugs often fail quietly. Pass a column name to a macro without quotes, and Jinja looks for a variable of that name. When none exists, the argument renders as nothing. The resulting SQL is broken, or worse, valid but wrong, and you'll only see why by reading target/compiled. To check what a variable holds while a model is rendering, the log function prints objects to the command line.

    Checkpoint 6 of 8· Fill the gap

    This macro call should convert the amount column. Which argument makes it compile to the intended SQL?

    {{ cents_to_dollars( ? ) }} as amount_usd

    Checkpoint 7 of 8· Exam question

    A teammate says `dbt run -s orders` keeps failing with what looks like the same error even after they edited `models/orders.sql` several times. Each proposed next action below is a complete, standalone step. Which single action is most likely to resolve the confusion?

    Sources145

    4.SQL you didn't write: hooks, merges and tests

    Some Database Errors come from queries dbt runs on its own, so the model's compiled select will look fine. dbt also sends introspective queries that list objects, statements that create schemas, pre- and post-hooks, on-run-start and on-run-end hooks, and the merge, update and insert statements behind incremental models and snapshots. None of those is in your model's select. All of them are in logs/dbt.log, or in Details in the dbt platform.

    A busy log is hard to read, so shrink it first. Clear the contents of logs/dbt.log, then run dbt run again for just the failing model. The file will then contain only the queries for that one failure, and the statement the warehouse rejected will be near the bottom.

    Failing tests are debugged the same way. Every test compiles to a query that returns the failing records. On the CLI, the compiled test queries are in target/compiled/schema_tests. In the dbt platform, click the failed test and open Details. Paste that SQL into a query editor and run it, and you see exactly which rows broke the assertion. To produce test SQL without running anything, dbt compile --select "resource_type:test" compiles every test node.

    Checkpoint 8 of 8· Check yourself

    An incremental model fails with a Database Error, but its compiled select in target/compiled runs cleanly in the query editor. Where should you look next?

    Sources16

    Exam traps

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

    1. 1.You must run dbt compile before dbt run so the compiled SQL exists.Why is that wrong?

      Building commands do their own compilation. dbt compile is a debugging tool, not a step in the pipeline.

      Covered in Producing compiled SQL on demand

    2. 2.A Jinja mistake such as an unquoted macro argument will always raise a compilation error.Why is that wrong?

      An unquoted name is treated as a variable. If that variable doesn't exist, it renders as nothing, so the bug only shows up in the compiled SQL.

      Covered in Is it your SQL or your Jinja?

    3. 3.Compiled SQL depends only on your project code, so compiling twice always gives the same result.Why is that wrong?

      Resources that use introspective queries are rendered from warehouse metadata, so their compiled SQL can change as that metadata changes.

      Covered in Producing compiled SQL on demand

    4. 4.If a model's compiled select runs cleanly, the Database Error can't have come from dbt.Why is that wrong?

      dbt also runs hooks, schema creation, and incremental merge/insert statements, and any of these can fail. The log records them all.

      Covered in SQL you didn't write: hooks, merges and tests

    Practise it for real

    See the gap between a model's Jinja and the SQL dbt actually sends to the warehouse

    1. 1.Run dbt compile --inline "select * from {{ ref('raw_orders') }}" against a project that has a raw_orders node

      Why: It shows what a ref resolves to without building anything

      You should see: dbt logs the compiled SQL to the terminal, in addition to writing to the target/ directory

    2. 2.Run dbt compile --select for one of your Jinja-heavy models, then open its file under target/compiled

      Why: The compiled select is the version you can paste into a query editor and run on its own

      You should see: A plain select statement with every ref and macro rendered

    3. 3.Run dbt show --select for the same model

      Why: It compiles the model again and runs it, so you see the rows your current code returns

      You should see: The first 5 rows of the query result printed in the terminal

    Stuck? Get a nudge

    If the compiled SQL is not what you expected, the bug is in the Jinja, not in the SQL.

    Sources

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

    1. 1.
      “The target/run directory contains the SQL dbt executes to build your models.”
      ↩︎ Where dbt writes the SQL it runs
      “The logs/dbt.log file contains all the queries that dbt runs, and additional logging.”
      ↩︎ Where dbt writes the SQL it runs
      “90% of the time, there's a mistake in the SQL of your model.”
      ↩︎ Is it your SQL or your Jinja?
      “Then, re-execute dbt run for just the problematic model. The logs will just have the output you're looking for.”
      ↩︎ SQL you didn't write: hooks, merges and tests
      “The target/compiled directory contains select statements that you can run in any query editor.”
      ↩︎ Key concept
      “For incremental models, and snapshots: merge, update and insert statements”
      ↩︎ Exam trap 4
      “it can be useful to show these side-by-side in your code editor.”
      ↩︎ Checkpoint
      “In these cases, you should check out the logs — this contains all the queries dbt has run.”
      ↩︎ Checkpoint
    2. 2.
      “Visually inspecting the compiled output of resource files. This is useful for validating complex Jinja logic or macro usage.”
      ↩︎ Producing compiled SQL on demand
      “This will log the compiled SQL to the terminal, in addition to writing to the target/ directory.”
      ↩︎ Producing compiled SQL on demand
      “dbt compile is not a pre-requisite of dbt run, or other building commands.”
      ↩︎ Exam trap 1
      “Compiled SQL for resources that use introspective queries may depend on metadata from your warehouse.”
      ↩︎ Exam trap 3
      “Parsing a project is enough to produce a manifest, however, keep in mind that the written-out manifest won't include compiled SQL.”
      ↩︎ Checkpoint
    3. 3.
      “If previewing a model, dbt will always compile and run the compiled query from source.”
      ↩︎ Producing compiled SQL on demand
    4. 4.
      “Use the error message and the compiled SQL to debug any errors.”
      ↩︎ Is it your SQL or your Jinja?
    5. 5.
      “You can also use the log function to debug Jinja by printing objects to the command line.”
      ↩︎ Is it your SQL or your Jinja?
    6. 6.
      “Navigate to the target/compiled/schema_tests directory for all compiled test queries.”
      ↩︎ SQL you didn't write: hooks, merges and tests

    Also cited

    Ready to test yourself?

    Practise the 11 questions on this subdomain.

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