dbt-labs/dbt-core · error · InvalidOperation
diff_of_two_dicts requires a dict_b argument
Error message
diff_of_two_dicts requires a dict_b argument
What it means
diff_of_two_dicts validates that a value for dict_b is available, either via the dict_b kwarg or the second positional argument. When neither is present the function throws this InvalidOperation error. It complements the dict_a check at base.rs:614.
Source
Thrown at crates/dbt-jinja-utils/src/functions/base.rs:626
}
let dict_a_arg = match (kwargs.get("dict_a"), args.first()) {
(Ok(value), _) => value,
(_, Some(value)) => value,
_ => {
return Err(Error::new(
ErrorKind::InvalidOperation,
"diff_of_two_dicts requires a dict_a argument",
));
}
}
.clone();
let dict_b_arg = match (kwargs.get("dict_b"), args.get(1)) {
(Ok(value), _) => value,
(_, Some(value)) => value,
_ => {
return Err(Error::new(
ErrorKind::InvalidOperation,
"diff_of_two_dicts requires a dict_b argument",
));
}
}
.clone();
let dict_a = parse_dict_of_lists(&dict_a_arg)?;
let dict_b = parse_dict_of_lists(&dict_b_arg)?;
// Convert dict_b to lowercase for case-insensitive comparison.
// IndexMap preserves insertion order so `diff_of_two_dicts` matches
// Python's dict semantics (iteration follows dict_a's insertion order),
// which apply_grants macros rely on for deterministic REVOKE/GRANT order.
let mut dict_b_lowered: IndexMap<String, Vec<String>> = IndexMap::new();
for (key, value_list) in dict_b {
dict_b_lowered.insert(
key.to_lowercase(),View on GitHub (pinned to 0267ce9170)
Solutions
- Supply the second dict positionally: diff_of_two_dicts(a, b)
- Or pass dict_b=... explicitly alongside dict_a
- If comparing against an empty dict intentionally, pass {} as the second argument
Example fix
// before
{% set diff = diff_of_two_dicts(my_dict) %}
// after
{% set diff = diff_of_two_dicts(my_dict, {}) %} Defensive patterns
Strategy: validation
Validate before calling
{% if dict_b is not defined %}
{{ exceptions.raise_compiler_error('dict_b is required for diff_of_two_dicts in ' ~ this) }}
{% endif %} Type guard
{% macro is_dict(x) %}{{ return(x is defined and x is mapping) }}{% endmacro %} Prevention
- Never call diff_of_two_dicts with a single dict; pass {} explicitly to diff against empty
- Verify the second argument survived refactors
- Use named kwargs to make both dicts obvious at the call site
When it happens
Trigger: Calling diff_of_two_dicts(a) with a single positional dict and no dict_b kwarg — the most common shape that reaches this branch. Also diff_of_two_dicts(dict_a=a) with only the dict_a kwarg.
Common situations: Developers assuming the function diffs against an implicit empty dict or the model config; partial refactors where the second dict argument was deleted; passing only one dict to compare 'with nothing'.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- diff_of_two_dicts requires a dict_a argument
- write function requires payload argument
- describe_dynamic_table is not supported by the {} adapter
- describe_interactive_table is not supported by the {} adapte
- get_csv_data requires agate_table argument
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/6970bc229048420a.
Report an issue: GitHub.