[Bug] Unit tests render the tested model with config.meta stripped to {}
- Dominant language
- Rust
- Stars
- 13.8k
- Forks
- 2.6k
- Avg merge
- 21h 31m
- Merged PRs (30d)
- 56
Description
### Is this a new bug in dbt-core?
- [x] I believe this is a new bug in dbt-core
- [x] I have searched the existing issues, and I could not find an existing issue for this bug
### Current Behavior
When dbt renders a tested model **inside a unit test**, the model's own `config.meta` is empty — regardless of whether it was set via `{{ config(meta={...}) }}` in the `.sql` file or via `config.meta:` in the model's `.yml`. The same Jinja that reads `config.meta` returns the configured dict during `dbt compile` / `dbt run`, but returns `{}` during `dbt test`.
The same behavior is observed on dbt Core 1.11.9 and on dbt Fusion 2.0.0-preview.175 — this isn't a Fusion regression, it's a Core-side gap that Fusion inherits.
Minimal public reproducer (dbt-duckdb, no creds required): https://github.com/ms-86/dbt-unit-test-meta-stripped-repro
| Source of `meta` | `dbt compile` (model) | `dbt test` (unit test) |
|------------------|----------------------|------------------------|
| `{{ config(meta={...}) }}` in `.sql` | visible | stripped to `{}` |
| `config.meta:` in `.yml` | visible | stripped to `{}` |
Concrete output from the repro:
```sql
-- target/compiled/unit_test_meta_repro/models/meta_probe.sql (normal render)
SELECT
CAST('True' AS VARCHAR) AS sql_block_flag,
CAST('set-from-sql' AS VARCHAR) AS sql_block_label,
CAST('set-from-yml' AS VARCHAR) AS yml_block_flag,
CAST('{...}' AS VARCHAR) AS meta_dict_repr
-- target/compiled/unit_test_meta_repro/models/meta_probe.yml/models/meta_probe_sees_meta.sql
SELECT
CAST('NOT_SET' AS VARCHAR) AS sql_block_flag,
CAST('NOT_SET' AS VARCHAR) AS sql_block_label,
CAST('NOT_SET' AS VARCHAR) AS yml_block_flag,
CAST('{}' AS VARCHAR) AS meta_dict_repr
```
### Expected Behavior
When dbt renders a tested model inside a unit test, `config.meta` should return the same dictionary that `dbt compile` / `dbt run` would see — the union of `meta` set via `{{ config(meta=...) }}` in `.sql` and `config.meta:` in `.yml`. Anything less makes meta-driven SQL switches untestable.
### Steps To Reproduce
```bash
git clone https://github.com/ms-86/dbt-unit-test-meta-stripped-repro
cd dbt-unit-test-meta-stripped-repro
uv sync
# Normal compile — config.meta IS visible
uv run dbt compile --profiles-dir . --select meta_probe
cat target/compiled/unit_test_meta_repro/models/meta_probe.sql
# → CAST('True' AS VARCHAR), CAST('set-from-sql' AS VARCHAR),
# CAST('set-from-yml' AS VARCHAR),
# CAST('{'sql_flag': True, ...}' AS VARCHAR)
# Unit test render — config.meta is empty
uv run dbt test --profiles-dir . --select meta_probe
cat target/compiled/unit_test_meta_repro/models/meta_probe.yml/models/meta_probe_sees_meta.sql
# → CAST('NOT_SET' AS VARCHAR), CAST('NOT_SET' AS VARCHAR),
# CAST('NOT_SET' AS VARCHAR), CAST('{}' AS VARCHAR)
```
### Relevant log output
```shell
Failure in unit_test meta_probe_sees_meta (models/meta_probe.yml)
actual differs from expected:
,sql_block_flag,sql_block_label,yml_block_flag,meta_dict_repr
+++,NOT_SET ,NOT_SET ,NOT_SET ,{}
---,True ,set-from-sql ,set-from-yml ,"{'sql_flag': True, 'sql_label': 'set-from-sql', 'yml_flag': 'set-from-yml'}"
```
### Environment
```markdown
- OS: macOS 15.7.3 (Darwin 24.6.0, arm64)
- Python: 3.12.12 (uv-managed venv in the repro project)
- dbt-core: 1.11.9 (latest patch on the 1.11 line)
- dbt-duckdb: 1.10.0
- Cross-checked on dbt-fusion 2.0.0-preview.175 — same behavior
```
### Which database adapter are you using with dbt?
other — duckdb. The bug is not adapter-specific; it lives in core's unit-test parser before adapter dispatch.
### Additional Context
**Root cause.** `core/dbt/parser/unit_tests.py` constructs the `UnitTestNode` with a fresh `UnitTestNodeConfig` carrying only `materialized`, `expected_rows`, and `expected_sql` — none of the tested model's config (including `meta`) is propagated:
```python
# core/dbt/parser/unit_tests.py (v1.11.9)
unit_test_node = UnitTestNode(
...,
config=UnitTestNodeConfig(
materialized="unit",
expected_rows=expected_rows,
expected_sql=expected_sql,
),
raw_code=tested_node.raw_code, # tested model's Jinja
...,
)
ctx = generate_parser_unit_test_context(unit_test_node, ...)
get_rendered(unit_test_node.raw_code, ctx, unit_test_node, capture_macros=True)
```
`UnitTestNodeConfig` is defined at `core/dbt/contracts/graph/model_config.py:39-41` and inherits from `NodeConfig`. `get_rendered` then renders the tested model's `raw_code` against this empty `UnitTestNodeConfig`, so `config.get('meta')` returns the default `{}`.
A minimal fix would copy `meta` (and possibly other relevant fields) from `tested_node.config` onto the `UnitTestNodeConfig` at construction time. The harder question is whether **all** of `tested_node.config` should be propagated, or just the fields a model body might reasonably introspect (`meta`, `tags`, model-level user-set keys). Either way, the current behavior — silently dropping the entire config — is surprising and breaks meta-driven SQL switches.
**Impact.** Several dbt packages switch SQL on `config.meta` toggles. The most prominent example is [**automate_dv**](https://github.com/Datavault-UK/automate-dv): `automate_dv.databricks__eff_sat` reads `is_auto_end_dating` via `automate_dv.config_meta_get(...)` ([`macros/tables/databricks/eff_sat.sql:11`](https://github.com/Datavault-UK/automate-dv/blob/master/macros/tables/databricks/eff_sat.sql#L11)).
`config_meta_get` ([`macros/supporting/fusion_compat.sql`](https://github.com/Datavault-UK/automate-dv/blob/master/macros/supporting/fusion_compat.sql)) probes **both** `config.get('meta').get(key)` and `config.get(key)`. The file is named `fusion_compat.sql` because it works around dbt Fusion's strict validation of custom top-level config keys ([dbt-fusion#511](https://github.com/dbt-labs/dbt-core/issues/13546)) — the helper itself is plain Jinja that runs on both engines.
The unit-test bug reported here defeats both lookup paths on both engines, because `UnitTestNodeConfig` is a blank slate. The auto-end-dating branch of `automate_dv.eff_sat` is therefore unreachable in any unit test. The same is true of any other macro that switches SQL on `config.meta`.
Contributor guide
Assessment
This issue has not been assessed yet.