Lineage integrity · rule dependency-cycle
dbt dependency cycles in the model DAG
A Metacenta review checks this under the rule The model DAG is acyclic. Everything below applies whether or not you ever commission one.
What this rule checks
This rule flags each dependency cycle among the models in a dbt manifest: a model that depends on itself through its chain of ref() calls. We report each cycle once and name every model in it. A manifest with no cycle passes.
Why it matters
No build order can satisfy a cycle, so dbt cannot build the project at all. dbt refuses to compile a cyclic project, so a cycle in the manifest means it was edited by hand or produced by a fork of dbt.
How to fix it
Break the loop of models that depend on each other. Move the logic both models share into a new upstream model, and ref() that from each side. Then regenerate the manifest with dbt parse and check the cycle is gone.
Before:
-- int_orders.sql
select order_id, amount
from {{ ref('int_payments') }}
-- int_payments.sql
select order_id, amount
from {{ ref('int_orders') }}
After:
-- int_order_payments.sql: the shared logic
select order_id, amount
from {{ ref('stg_payments') }}
-- int_orders.sql
select order_id, amount
from {{ ref('int_order_payments') }}
-- int_payments.sql
select order_id, amount
from {{ ref('int_order_payments') }}
When it is fine to leave
None in a dbt project, because dbt will not compile one. If this fires, look first at how the manifest was produced. A manifest rewritten by a script, or built by a patched dbt, is the usual cause.
What we need to check it
manifest.json alone, which dbt parse writes. The rule declines when the manifest declares no models.