---
title: "dbt models with no ref() or source() | Metacenta"
description: "A dbt model that declares no ref() and no source() is reading something dbt cannot see. Which models we leave alone, and how to declare the input."
url: "https://metacenta.com/rules/root-model"
updated: "2026-10-14"
tokens: 661
---

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's only a macro call is flagged, because the macro can read a table we can't 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:

```sql
select country_code, country_name
from reference.countries
```

After:

```sql
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 can't recognise a model that generates its own rows, so it's flagged. The rule declines when the manifest declares no models.

## Published rules it corresponds to

**[dbt_project_evaluator](https://dbt-labs.github.io/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.

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

## Related pages

- [dbt dependency cycles in the model DAG](https://metacenta.com/rules/dependency-cycle)
- [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)
- [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)
