Lineage integrity · rule root-model
dbt models with no ref() or source()
A Metacenta review checks this under the rule Every model declares where its data comes from. Everything below applies whether or not you ever commission one.
What this rule checks
This rule flags dbt models that declare no ref() and no source(). A model whose SQL visibly generates its own rows passes, such as a select of literals or one reading only CTEs and table functions like unnest. MetricFlow time spines are left out. A body that is only a macro call is flagged, because the macro can read a table we cannot see.
Why it matters
dbt cannot place the model in the build order or rebuild it when its input changes. Whatever it reads can go stale without anything failing.
How to fix it
Declare where every model's data comes from. Declare the table the model reads as a source in your YAML, and read it with {{ source() }}. If the model genuinely generates its own rows, say so in its description.
Before:
select country_code, country_name
from reference.countries
After:
select country_code, country_name
from {{ source('reference', 'countries') }}
When it is fine to leave
A model built wholly by a macro that reads nothing, such as a generated calendar, has no parent by design. Leave it, and say so in its description. We report the finding at medium confidence because such models exist.
What we need to check it
manifest.json alone, with each model's raw_code where present. Without the SQL we cannot recognise a model that generates its own rows, so it is flagged. The rule declines when the manifest declares no models.
Published rules it corresponds to
dbt_project_evaluator, rule fct_root_models. Ours checks the same condition and threshold.
This means our check corresponds to their rule. It does not mean the publisher reviewed or endorses it.