---
title: "dbt dependency cycles in the model DAG | Metacenta"
description: "A dbt manifest with a dependency cycle cannot be built. What a cycle in the manifest tells you about how it was made, and how to break one."
url: "https://metacenta.com/rules/dependency-cycle"
updated: "2026-10-14"
tokens: 609
---

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:

```sql
-- int_orders.sql
select order_id, amount
from {{ ref('int_payments') }}

-- int_payments.sql
select order_id, amount
from {{ ref('int_orders') }}
```

After:

```sql
-- 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.

[Ask about a review](https://metacenta.com/enquire?src=rule-dependency-cycle&via=md)

## Related pages

- [dbt models with a hardcoded table name](https://metacenta.com/rules/hardcoded-table-reference)
- [dbt exposures: what they are and how to declare them](https://metacenta.com/rules/model-possibly-unused)
- [Deep dbt lineage: long chains of models](https://metacenta.com/rules/deep-lineage)
- [dbt models with too many direct dependents](https://metacenta.com/rules/fan-out-hotspot)
- [A sample review, as a client reads it](https://metacenta.com/sample)
- [All published rules](https://metacenta.com/rules)
- [How a review is assessed](https://metacenta.com/standard)
