dbt dependency cycle detected, models fail to compile
Breaks dbt dependency cycles: how cycles form through refs, how to find the loop, and how to restructure the models. Use when dbt fails compilation with a dependency cycle error. Not for slow builds without cycles.
TL;DR
A dependency cycle means model A refs model B which refs model A, directly or through a chain, and dbt cannot order the build. Read the cycle error for the model names in the loop, then break it: usually by extracting the shared logic into a third model both sides ref, or by removing a ref that should have been a source. Cycles are a modeling problem, not a dbt bug.
dbt dependency cycle detected, models fail to compileUse this when
- dbt compile fails naming a dependency cycle.
- Two models grew refs to each other over time.
- A refactor introduced the cycle.
Not for this skill when
- Builds are slow but compile fine. That is performance, not a cycle.
- A single model fails. Look at its SQL, not the graph.
Steps
- Read the cycle error and list the models in the loop. Note the full chain. Verify: the loop is mapped
- For each ref in the loop, ask which direction the data really flows. Note the ref that goes the wrong way. Verify: the offending edge is found
- Extract the shared logic into a new intermediate model that both sides ref, or replace the backward ref with a source. Note the graph is acyclic. Verify: the cycle is broken structurally
- Re-run dbt compile and confirm the graph builds. Note compilation succeeds. Verify: the build works
- Review the project's layering (staging, intermediate, marts) so the pattern is not reintroduced. Note the convention is documented. Verify: the pattern stays fixed
Variant phrasings
dbt circular dependency
The common paraphrase.
dbt cycle in dag
The graph-shaped search.
Compatibility: dbt Core 1.x. Cycle detection runs at parse time on all adapters.
Why it happens
dbt builds a directed acyclic graph of your project, and acyclic is load-bearing: it determines build order. Cycles creep in when two models both need a piece of each other's logic, which usually means that logic belongs in a third model neither of them owns yet. The error lists the loop because the fix is always about the shape of the graph, not about any single model's SQL. Refactors that merge or split models are the usual moment a cycle appears.
Edge cases / pitfalls
- Self-referencing models (a model refing itself) are cycles of length one. Rename or split the model.
- Macros do not create cycles, but a macro that generates refs can hide one. Expand the macro output when hunting the loop.
- Ephemeral models participate in the graph too. A cycle through an ephemeral model is still a cycle.
- Tests and exposures do not create cycles. Only refs between models count.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_s2uNuTgeDhrdv4q61Yr22w