Troubleshooting and optimizing dbt pipelines: sample questions

3 free practice questions on troubleshooting and optimizing dbt pipelines, one of the seven topics in the official v1.11 outline for the dbt Analytics Engineering Certification Exam — an estimated 6% of the exam, or about 4 of its 65 questions. Answers, reasoning and documentation links are all on this page.

Last updated . We revise these pages whenever dbt Labs revises the exam.

SHARE OF THE EXAM~6%our estimate
QUESTIONS HERE31 with runnable SQL
FORMATS SHOWN2of 6 on the exam

What this topic covers

A small topic with two subtopics: managing failure points in the DAG, and using dbt clone.

SUBTOPICS, FROM THE OFFICIAL OUTLINE · 2

  1. 01Troubleshooting and managing failure points in the DAG
  2. 02Using dbt clone

Where the marks go

Two ideas carry it. First, an errored node is a node-level failure, not a run-level abort — dbt continues through the rest of the DAG and marks only that node's dependents as skipped, unless you pass --fail-fast. The discrete-option question below tests the consequences one statement at a time.

Second, dbt clone does not rebuild anything. It points at the relations recorded in the state manifest you hand it, which means a QA schema stood up by cloning holds production's data as of production's last run — not as of now, however many rows have landed since.

3 sample questions, with answers

Nothing is hidden. Each question shows the correct answer, why it is right, why every other option is wrong, and the documentation page that settles it. Where the answer is a claim about SQL behaviour, there is a query you can run in the browser against a small sample schema.

Q1Multiple choiceMedium

A nightly dbt build finishes with this summary line. The two WARN results are generic tests configured with severity: warn, and no --fail-fast flag is set. Which statement regarding this run is true?

Finished running 38 models, 2 snapshots, 10 tests in 0 hours 6 minutes and 12.44 seconds (372.44s).
Completed with 1 error and 2 warnings:
Done. PASS=41 WARN=2 ERROR=1 SKIP=6 TOTAL=50
  • The 6 SKIP nodes are every node that had not started when the error occurred.
  • The 6 SKIP nodes are all downstream of the node counted in ERROR.CORRECT
  • The 2 WARN results are tests that returned failing rows at default severity.
  • The 2 WARN results each skipped the models downstream of them.

WHY

The summary line buckets every selected node exactly once, and the four counts sum to TOTAL (41+2+1+6=50). SKIP counts nodes dbt never executed because something they depend on did not succeed — the build docs state that a failure blocks downstream resources and causes them to 'skip entirely' (e.g. if model_b depends on model_a and a unique test on model_a fails, model_b will SKIP). Here only one node is counted in ERROR, and the two WARN results come from tests set to severity: warn, which the same page says is how you stop a test from causing skipping. So the only blocking failure in the run is the ERROR node, and all 6 skipped nodes are its descendants (directly, or through another skipped node). That is what a non-zero SKIP buys you when triaging: it is a count of unrun work traceable to an upstream failure, not of work that ran badly.

WHY THE OTHERS ARE WRONG

The 6 SKIP nodes are every node that had not started when the error occurred.
That describes --fail-fast, which is not set here. Without it dbt keeps executing nodes that do not depend on the failed one, so SKIP=6 is the count of that node's descendants, not the count of everything left in the run.
The 2 WARN results are tests that returned failing rows at default severity.
Default severity is error, not warn: a test that returns failing rows at default severity is a failure and lands in the ERROR bucket. A result only lands in WARN when severity is warn, or when the failure count clears warn_if but stays under error_if.
The 2 WARN results each skipped the models downstream of them.
Warn-severity tests are exactly the case that does not skip anything — the build page's advice for 'don't want a test to cause skipping?' is to set severity to warn instead of error. Downstream models of those two tests were built and are counted in PASS.
Q2Multiple choiceMediumRunnable proof

Your project runs on Snowflake. In production, fct_orders is materialized as a table and stg_orders as a view. From your dev target you run dbt clone --state prod-artifacts --select stg_orders fct_orders. Which statement regarding the relations created in dev is true?

  • fct_orders is a zero-copy clone; stg_orders is skipped as a non-cloneable node.
  • fct_orders is a zero-copy clone; stg_orders is a view pointing at the production relation.CORRECT
  • fct_orders is a zero-copy clone; stg_orders is rebuilt by executing its model SQL.
  • Both relations are created as views pointing at the production relations.
  • Both relations are created as zero-copy clones of the production relations.

WHY

The clone materialization applies a two-part test to each selected node: dbt creates a zero-copy clone only if the data platform supports zero-copy cloning of tables AND the node exists as a table in the source environment. Otherwise it creates a simple view that references the relation in the source environment. Snowflake satisfies the platform half for both nodes, so fct_orders (a table in production) is cloned via metadata only. stg_orders fails the second half — it is a view in production, not a table — so dbt falls back to a pointer view in dev defined over the production relation. That fallback is per node, not per project, which is why one clone command can leave two different object types in the same dev schema.

WHY THE OTHERS ARE WRONG

fct_orders is a zero-copy clone; stg_orders is skipped as a non-cloneable node.
dbt does not skip nodes that cannot be zero-copy cloned. The clone materialization has a documented fallback — a view referencing the source relation — so stg_orders is still created in the dev schema.
fct_orders is a zero-copy clone; stg_orders is rebuilt by executing its model SQL.
dbt clone never executes model SQL — that is what distinguishes it from dbt run. The fallback view simply selects from the relation in the source environment; the model's own compiled SQL is not run.
Both relations are created as views pointing at the production relations.
The view fallback applies only to nodes that fail the table-and-platform test. fct_orders is a table on a platform that supports zero-copy cloning, so it is cloned rather than pointed at.
Both relations are created as zero-copy clones of the production relations.
Platform support alone is not sufficient. Snowflake can zero-copy clone tables, but stg_orders is a view in the source environment, so the second condition fails and dbt creates a pointer view instead.
Q3Discrete option (DOMC)Medium

During a nightly dbt build, stg_orders errors and fct_orders, which refs it, is marked SKIP. You will be shown statements about fct_orders and how that run ends, one at a time. For each statement, answer YES if it is true, NO if it is false.

In the exam these appear one at a time and you answer YES or NO to each, without seeing the rest. All of them, with their answers, are below.

  • No SQL for fct_orders runs, so its table still holds the data from the previous buildYES
  • dbt retry rebuilds fct_orders without rerunning the models that already succeededYES
  • dbt creates fct_orders as an empty table so that downstream refs still resolveNO
  • The invocation exits with code 0, since a skip is not an errorNO
  • The non-zero exit code comes from the error on stg_orders, not from the skipYES

WHY

SKIP means the node never executed. dbt blocks a failed node's dependents from running and they 'skip entirely' — no CREATE, no INSERT, no query of any kind is sent for fct_orders, so whatever relation the previous successful build left in the warehouse is still sitting there untouched, now silently stale against the fresh stg_orders data (a). That skip state is written to target/run_results.json, which is exactly what dbt retry reads: retry re-executes the last invocation from the point of failure, so it rebuilds stg_orders and the nodes that skipped behind it, and picks up from the error rather than running all the upstream dependencies again (b). On exit codes, dbt returns 1 when the invocation completes with at least one handled error — the docs describe that case as the run completing while 'some models may have been skipped'. The skip is a downstream consequence of the handled error on stg_orders, which is what drives the non-zero code (e).

WHY THE OTHERS ARE WRONG

dbt creates fct_orders as an empty table so that downstream refs still resolve
dbt does not stand in an empty placeholder for a skipped node. The node is blocked from running at all, so nothing is created or replaced — an empty table would be worse than a skip, because downstream models would build cleanly on zero rows and publish an empty mart instead of failing loudly.
The invocation exits with code 0, since a skip is not an error
A zero exit code always implies success. This run had a handled error (stg_orders), so dbt exits 1; skips are reported alongside that error, not as a clean outcome.

Know whether troubleshooting and optimizing dbt pipelines is actually costing you marks.

The free readiness check is weighted like the real exam across all seven topics, so it tells you where you stand on this topic relative to the rest — which is the only version of that question worth answering before you book.

Take the free readiness check20 questions · ~15 minutes · no card

The other six topics

Keep reading

SOURCES

Every source above was read in full and last checked on .