dbt-labs / dbt-labs/dbt

[SQL] Fusion does not flag an un-ref()'d relation; bare name silently binds to a same-named table and builds an empty table reported as success

Open
#15,395 0 comments 0 reactions 0 assignees View on GitHub
status:triage
Dominant language
Rust
Stars
13.8k
Forks
2.6k
Avg merge
21h 31m
Merged PRs (30d)
56

Description

### Before you submit
- [x] I have searched the existing issues and could not find a duplicate

### SQL that dbt Fusion doesn't understand

```sql
with

cte_items as (
select order_id, sku from {{ ref('raw_items') }}
),

-- The ref() was forgotten: `raw_stores` is written as a bare name. It is not a ref(),
-- source, or CTE, but a table of that name exists in the target schema, so Fusion resolves
-- it silently and creates no lineage edge / no warning. Its `id` never equals an item `sku`.
orders_with_activity as (
select distinct cte_items.order_id
from cte_items
inner join raw_stores on raw_stores.id = cte_items.sku
)

select * from orders_with_activity
```

### What dbt Fusion does

Image

```shell
# render + analyze both pass, then the warehouse runs it and the model succeeds empty
Finished rendering model ... repro_empty_via_raw_seed [success]
Finished analyzing model ... repro_empty_via_raw_seed [success]
Succeeded [ 1.27s] model AAAA_SELFHOSTED.repro_empty_via_raw_seed (table)
Summary: 1 total | 1 success

# No warning or error is raised about the bare `raw_stores` reference.
# The compiled SQL qualifies the ref()'d relations but leaves the forgotten one bare:
# from analytics.AAAA_SELFHOSTED.raw_items <- ref(), schema-qualified
# inner join raw_stores ... <- forgotten ref, left bare
# raw_stores.id never equals an item sku -> the table is built with 0 rows.
```

Net effect: a forgotten `ref()` produces a silently empty table and a successful run.

### What you expected

Fusion's static analysis builds a schema store / catalog and resolves column lineage, so it has the information to detect this before execution. A relation that is neither a `ref()`, a `source()`, nor a CTE — particularly when a node or object of that name exists in the project or schema — should be **surfaced at compile/analyze time** (warning or error), rather than silently bound to an arbitrary same-named object at runtime. The forgotten ref should not be able to ship an empty production table under a successful run.

### What kind of SQL understanding issue is this?
- Wrong column lineage / ref resolution

### Which database adapter are you using?
- snowflake

### Does this SQL execute correctly with `--static-analysis off`, or when run by dbt Core?
- [x] Yes — this SQL is accepted by the warehouse (the bare name resolves to an existing object; the run succeeds and builds an empty table)

### Environment

```markdown
- dbt Fusion version: 2.0.0-preview.186 and 2.0.0-preview.193 (`dbt --version`)
- adapter: dbt-snowflake (v2)
- OS: macOS (darwin, aarch64)
```

### Additional Context

- **Behavior is identical on `2.0.0-preview.186` and the latest `2.0.0-preview.193`** (verified via `dbt system update` then re-run) — not a transient preview regression.
- dbt core fails with a database error (`dbt=1.11.0-b3`)
```
13:34:28 Failure in model repro_empty_via_raw_seed (models/repro_cte_pruning/repro_empty_via_raw_seed.sql)
13:34:28 Database Error in model repro_empty_via_raw_seed (models/repro_cte_pruning/repro_empty_via_raw_seed.sql)
002003 (42S02): SQL compilation error:
Object 'ANALYTICS.AAAA_SELFHOSTED.RAW_ORDERS' does not exist or not authorized.
compiled code at target/run/jaffle_shop/models/repro_cte_pruning/repro_empty_via_raw_seed.sql
13:34:28
13:34:28 compiled code at target/compiled/jaffle_shop/models/repro_cte_pruning/repro_empty_via_raw_seed.sql
```

- Deterministic: re-seeding the bare-referenced object with `--full-refresh` and rebuilding repeatedly yields the same silent success, so it is not a caching/stale-state artifact.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.