dbt: 'source' is undefined in staging model
"dbt: 'source' is undefined in staging model": # dbt: 'source' is undefined in staging model ## TL;DR `'source' is undefined` is Jinja telling you the `source()` *function itself* is missing from the rendering context, not that your source is misnamed.
dbt: 'source' is undefined in staging model
TL;DR
'source' is undefined is Jinja telling you the source() function itself is missing from the rendering context, not that your source is misnamed. dbt only injects source() into model, test, snapshot, and macro rendering contexts. The usual cause: the {{ source(...) }} call sits inside a {% docs %} block (docs blocks get a bare context that only provides doc()), or inside a macro or hook that is rendered outside a model. Move the source() call into the model SQL body and the error goes away.
Compilation Error in model stg_orders (models/staging/stg_orders.sql)
'source' is undefinedSteps
1. Find the exact source( call that fails
Run the compile with debug output and see which file Jinja was rendering when it failed:
dbt compile --select stg_orders --debug 2>&1 | grep -B5 "is undefined" | head -40Expected: a traceback naming a file and line. If it names a .md docs file, a schema.yml, or anything other than your model's .sql body, that location is the whole diagnosis.
2. Check whether the call is inside a {% docs %} block
Open the flagged file and look for {% docs %} / {% enddocs %} around the {{ source(...) }} call. Docs blocks render with a minimal context that only provides doc() — source() and ref() do not exist there.
If that is the case, replace the dynamic call with static text. Docs are rendered once as documentation; they cannot resolve warehouse relations:
{% docs stg_orders__table %}
This model reads from the raw orders table in the jaffle_shop source.
{% enddocs %}Expected: no {{ source( calls remain inside docs blocks. Verify with:
grep -rn "{{ source(" models/staging/*.md models/staging/schema.yml | grep -i "docs" | head3. Check macros and hooks
If the call is inside a macro, check every place that macro is invoked. A macro called from a model body has source(); the same macro called from a docs block or an on-run-start / on-run-end hook does not. Fix it by resolving the relation in the model and passing it in as an argument:
-- in the model (this context has source()):
{{ my_macro(source('jaffle_shop', 'orders')) }}-- in macros/my_macro.sql (takes the resolved relation as an argument):
{% macro my_macro(orders_relation) %}
select * from {{ orders_relation }}
{% endmacro %}Expected: the macro body contains no bare source() calls of its own.
4. Recompile the model
dbt compile --select stg_ordersExpected: Done. with no compilation error, and the compiled SQL under target/compiled/[project]/models/staging/stg_orders.sql contains the fully resolved table name (for example raw.jaffle_shop.orders).
When to use this skill
- The error text is exactly
'source' is undefined(a JinjaUndefinedError) naming thesourcefunction itself. dbt compile,dbt run,dbt parse, ordbt docsfails while rendering a model, a docs block, or a macro.
When NOT to use this skill
- The error names a specific source, for example
Source 'jaffle_shop' not foundordepends on a source named X which was not found. That meanssource()ran fine but the name matches nosources:declaration: checksources.ymlnames instead. - The undefined name is
ref,var, orconfigrather thansource. Same family of problem, different function.
Variant phrasings
Compilation Error: 'source' is undefined
dbt surfaces this as Compilation Error in model [name] ([path]) followed by 'source' is undefined. Same cause, same fix.
dbt Jinja UndefinedError on source()
Any jinja2.exceptions.UndefinedError: 'source' is undefined traceback during dbt parse, dbt compile, or dbt run is this issue.
Why it happens
dbt renders different files with different Jinja contexts. source() is a context function dbt injects when rendering models, tests, snapshots, and macros invoked from them. Documentation blocks ({% docs %}) are rendered with a docs-only context that provides just doc() plus base variables, so any source() call inside one is an undefined name to Jinja. The fix is structural: keep relation-resolving calls in the model SQL, keep docs as static text.
Edge cases
- The traceback points at your model's
.sqlfile directly and the call is in the body: look for a second file defining the same model name, or a{% docs %}block embedded in the.sqlfile itself. Also confirm the file sits under a parsedmodel-pathsdirectory; a file dbt parses as something other than a model gets a different context. - dbt Cloud and dbt CLI use the same rendering contexts, so the fix does not depend on where you run dbt.
- If you are on the dbt Fusion engine, malformed zero-argument
source()calls now get a located error instead of a panic, but the docs-block scoping rule is unchanged.
Matched thread
Source: Vectle search thread Original query: ""dbt: 'source' is undefined in staging model"" Key terms: model, source, staging, undefined
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.