Doc blocks look like they support Jinja because they use {% docs %} / {% enddocs %} tags and live in .md files that dbt’s Jinja parser processes. But the Jinja context inside a doc block is heavily restricted, and misunderstanding this causes errors that are confusing to debug.
The Restricted Context
Doc blocks are compiled with a minimal Jinja context. The key functions that are not available inside doc blocks:
ref()— you cannot reference modelssource()— you cannot reference sourcesconfig()— no configuration contextvar()— no project variables- Most other dbt Jinja functions
The doc() function itself does work, meaning you can reference one doc block from within another. But that is essentially the only dbt-specific function available.
If you try something like this inside a doc block:
{% docs order_status %}See {{ ref('stg_orders') }} for the raw status values.{% enddocs %}You will get a 'ref' is undefined error during compilation. The workaround for cross-referencing models is to use internal URL paths instead:
{% docs order_status %}See [stg_orders](#!/model/model.my_project.stg_orders) for the raw status values.{% enddocs %}The README Parsing Gotcha
dbt’s Jinja parser processes all .md files in your resource paths, not just files containing doc blocks. This catches people off guard when they have a README.md in their models directory.
If your README contains anything that looks like Jinja syntax — {{ something }}, {% block %}, even code examples showing Jinja — the parser will try to evaluate it and fail with 'ref' is undefined or similar errors.
Two solutions:
- Move READMEs out of resource paths. Keep documentation in a top-level
docs/folder that is not listed inmodel-paths,seed-paths, or other resource path configurations. - Avoid Jinja-like syntax in READMEs. If you must have a README in a models directory, use code blocks or escape any
{{/{%sequences. You can use{% raw %}...{% endraw %}to prevent Jinja processing of a block.
This gotcha also applies to any .md files pulled in by dbt packages. If a package includes Markdown files with Jinja-like syntax in its resource paths, those files will be parsed too.
The Missing Feature: Column Description Inheritance
One of the most requested features in dbt is column description inheritance — where downstream models automatically pick up column descriptions from their upstream parents. If you describe customer_id in your base model, every intermediate and mart model that uses that column would inherit the description without you doing anything.
This is tracked as GitHub issue #1158 and has not been implemented natively as of early 2026.
Without native inheritance, you have two options for avoiding description duplication:
Shared Doc Blocks
Define a doc block for each common column and reference it explicitly everywhere:
# In base model YAMLcolumns: - name: customer_id description: "{{ doc('customer_id') }}"
# In mart model YAML -- same referencecolumns: - name: customer_id description: "{{ doc('customer_id') }}"This requires you to add the {{ doc() }} reference in every model’s YAML, but at least the description text is defined in one place. Change the doc block and it updates everywhere.
dbt-osmosis Propagation
dbt-osmosis solves this more automatically. It traces column lineage through your DAG and copies descriptions from upstream models to downstream ones. Running dbt-osmosis yaml refactor propagates descriptions without requiring doc block references at all — it simply copies the text into each model’s YAML.
The tradeoff: dbt-osmosis duplicates the text (so each YAML file has its own copy of the description), while doc blocks keep a single source of truth. For most teams, dbt-osmosis is less maintenance because it runs automatically, but doc blocks give you stronger guarantees about consistency.
Practical Implications
These limitations shape how you architect your documentation:
- Use doc blocks for the description text itself, and
#!/model/...URL paths for cross-references between models - Keep non-doc-block Markdown files out of resource paths, or wrap their content in
{% raw %}tags - For column description reuse, choose between shared doc blocks (single source of truth, more setup) and dbt-osmosis (automated propagation, duplicated text). Both solve the problem; they trade off differently