[Bug] Unit test raising error `'<macro name>' is undefined. This can happen when calling a macro that does not exist.`
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
Sometimes (but not always!), I get this compilation error when a model contains a macro:
13:04:08 Compilation Error in unit_test test__model_f (models/unit_test.yml)
'british_colours' is undefined. This can happen when calling a macro that does not exist. Check for typos and/or install package dependencies with "dbt deps".
Expected Behavior
This seems like it should work without needing to add an override for any macros.
Steps To Reproduce
macros/my_macros.sql
{% macro british_colours() -%}
{{ return(["grey"]) }}
{%- endmacro %}
{% macro american_colors() -%}
{{ return(["gray"]) }}
{%- endmacro %}
models/_unit_tests.yml
unit_tests:
- name: test__model_f
model: model_f
given: []
expect:
rows:
- {id: 1}
models/model_f.sql
{% set a_values = british_colours() %}
{% set b_values = american_colors() %}
select 1 as id
Build and see that everything works just fine:
dbt build -s +model_f
Update models/model_f.sql to add {% set ab_values = a_values + b_values %} anywhere within the model defintion:
{% set a_values = british_colours() %}
{% set b_values = american_colors() %}
{% set ab_values = a_values + b_values %}
select 1 as id
Now re-build and see the error:
dbt build -s +model_f
13:12:43 Completed with 1 error and 0 warnings:
13:12:43
13:12:43 Compilation Error in unit_test test__model_f (models/unit_test.yml)
'british_colours' is undefined. This can happen when calling a macro that does not exist. Check for typos and/or install package dependencies with "dbt deps".
Relevant log output
See above
Environment
- OS:
- Python:
- dbt:
Which database adapter are you using with dbt?
postgres
Additional Context
Found while researching https://github.com/dbt-labs/dbt-core/issues/10139.
Worth confirming would this happen by itself without unittest
This works fine for me if I do not have any dbt unit tests defined:
dbt build -s +model_f
But if I add a dbt unit test and re-run that same command, then it gives the error.
I can confirm that I'm experiencing this as well.
Context
I'm using dbt-core 1.8.3 with dbt-snowflake 1.8.3 on macOS Ventura 13.6.
I'm developing a custom dbt package which defines a suite of macros. I'm experiencing the error in my package's integration_tests project. I have an example model which calls my_package.my_macro(...) in its logic. I've also written an example unit test for the model to verify its functionality. When running the project with dbt run, the model runs as-expected and the compiled code in target/run and target/compiled reflects the expected macro output.
When running either dbt build or dbt test on the project, however, I get the "macro is not defined" error mentioned above.
Please let us know when you've root-caused this bug, since it will be a huge roadblock for me and my team to pivot to using native DBT unit tests as opposed to the EqualExperts unit testing framework (which doesn't seem to suffer from this bug).
Thanks in advance!
Thanks for sharing some of the specifics of your scenario @dsillman2000 👍
If a constant return value is sufficient for the purposes of your unit test, a workaround is to use an overrides configuration like this:
macros:
# explicity set star to relevant list of columns
dbt_utils.star: col_a,col_b,col_c
Otherwise, there isn't a known workaround.
You can stay subscribed to this issue in GitHub to get notified of updates regarding further root cause or resolution.
I am having the same issue, I have a macros named "test_macro.sql":
{% macro test_macro() %} {{ return('This is a test macro') }} {% endmacro %}
in dbt_project.yml I have set up the path correctly and call the macros:
macro-paths: ["macros"] ... generate_schema_name: "{{ test_macro() }}"
But when I run dbt debug I got this error:
Could not render {{ test_macro() }}: 'test_macro' is undefined
Have anyone firgured out with happened?
@Goal1803 it sounds like you're dealing with a different issue, unrelated to unit tests.
You cannot call a macro directly in the dbt_project.yml as these are parsed at different times. There's a discussion on this here -> https://github.com/dbt-labs/dbt-core/discussions/9172
Thanks for sharing some of the specifics of your scenario @dsillman2000 👍
If a constant return value is sufficient for the purposes of your unit test, a workaround is to use an
overridesconfiguration like this:macros: # explicity set star to relevant list of columns dbt_utils.star: col_a,col_b,col_cOtherwise, there isn't a known workaround.
You can stay subscribed to this issue in GitHub to get notified of updates regarding further root cause or resolution.
I'm running into this issue again, in a new project, with a macro defined within the project (more similar to the minimum reproducible example above). Unfortunately, even setting an overrides configuration for the macro does not fix the issue, as it is still complaining that it's unable to find the macro even when I give it a direct, constant override value to return.
I don't know if this should be filed as a separate bug with the overrides configuration not working, since I've been able to override macros in other projects, but not when encountering the "macro not found" bug. Even when defining an override for the "missing" macro, the parser is still unhappy.
"Overrides" section of the subject unit test case:
unit_tests:
- name: parse_legacy_tool_events
description: |-
Shall correctly parse tool events from legacy software versions into a consistent
"SupportLogEvent" format.
model: stg_support_log_tool_events_legacy
overrides:
macros:
legacy_support_log_sw_versions: 'my_constant_value'
given: ...
After running dbt test:
'legacy_support_log_sw_versions' is undefined. This can happen when calling a macro that does not exist. Check for typos and/or install package dependencies with "dbt deps".
Running the same model with dbt run works fine, since the macro is valid & defined within the project. But it cannot be found during unit testing, and apparently the override does not apply to it.
As with my testimony above, I'm using dbt-core 1.8.3 and dbt-snowflake 1.8.3 macOS Ventura 13.6.
Moments after posting above, I had a breakthrough @dbeatty10 ! Please try it in your minimum reproducible example project to see if it works / helps you root cause the issue.
Work-around:
- Call the macro inside of a set block, e.g.:
{% set legacy_versions %}{{ legacy_support_log_sw_versions() }}{% endset %}
- Reference the previously-set value, instead of calling the macro itself:
select * from {{ source(...) }} where software_version_id in ({{ legacy_versions }})
- ???
- Profit!
Note that this also allows the overrides value to propagate correctly. So the bug must be upstream of the overriding stage of dbt's parser. It's also noteworthy that using the return value of the macro in a set tag (i.e. {% set value = macro_name() %}) does not work, but using the set block syntax does work.
This suggests to me that the broken link must be in how dbt is resolving macros differently in a set block context as opposed to other contexts. Please let me know if you're able to reproduce this work-around in your example case above!
I believe I've got a similar issue, we override the source macro to give us the option to include the database when the relation is expanded.
{% macro source(source_name, table_name, include_database=False) %}
{% do return(builtins.source(source_name, table_name).include(database=include_database)) %}
{% endmacro %}
When running a unit test on a model that includes the additional parameter to source() we get:
10:20:22 Compilation Error in unit_test Daily_TimeSeries_Incremental_UT (models\Nav\Nav.yml) source() takes exactly two arguments (3 given)
Slightly different error message but I suspect it's a similar cause in the custom macros not being evaluated during unit test compilation
We are really keen to maximise the use of dbt's unit testing. Is there a feature request to support use of 3rd party macros ? We use them extensively and wrapping all the macros in another macro to allow unit testing seems very much like a heavy handed approach to getting this to work ?
The example on the documentation site uses dbt_utils - that also comes from dbt hub. If I use a macro from that package then unit testing works .. assuming i've run dbt deps before hand