{"record":{"id":"782b752ecb939e00","repo":"dbt-labs/dbt-core","slug":"diff-of-two-dicts-requires-exactly-2-arguments","errorCode":null,"errorMessage":"diff_of_two_dicts requires exactly 2 arguments","messagePattern":"diff_of_two_dicts requires exactly 2 arguments","errorType":"validation","errorClass":"InvalidOperation","httpStatus":null,"severity":"error","filePath":"crates/dbt-jinja-utils/src/functions/base.rs","lineNumber":604,"sourceCode":"        let sorted_map: BTreeMap<_, _> = obj.iter().map(|(k, v)| (k.clone(), v.clone())).collect();\n        *obj = sorted_map.into_iter().collect();\n    }\n\n    match dbt_yaml::to_string(&json_value) {\n        Ok(yaml_str) => Ok(Value::from(yaml_str)),\n        Err(err) => Err(Error::new(\n            ErrorKind::InvalidOperation,\n            format!(\"Failed to convert value to YAML: {err}\"),\n        )),\n    }\n}\n\n/// A function that returns the difference between two dictionaries\n/// Not documented in dbt Jinja docs, but included in base.py\npub fn diff_of_two_dicts_fn() -> impl Fn(&[Value], Kwargs) -> Result<Value, Error> {\n    move |args: &[Value], kwargs: Kwargs| -> Result<Value, Error> {\n        if args.len() != 2 {\n            return Err(Error::new(\n                ErrorKind::InvalidOperation,\n                \"diff_of_two_dicts requires exactly 2 arguments\",\n            ));\n        }\n\n        let dict_a_arg = match (kwargs.get(\"dict_a\"), args.first()) {\n            (Ok(value), _) => value,\n            (_, Some(value)) => value,\n            _ => {\n                return Err(Error::new(\n                    ErrorKind::InvalidOperation,\n                    \"diff_of_two_dicts requires a dict_a argument\",\n                ));\n            }\n        }\n        .clone();\n\n        let dict_b_arg = match (kwargs.get(\"dict_b\"), args.get(1)) {","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-jinja-utils/src/functions/base.rs#L586-L622","documentation":"diff_of_two_dicts is a dbt Jinja helper (mirroring dbt-core's base.py) that returns the difference between two dictionaries. The Rust implementation requires exactly two positional arguments (or the dict_a/dict_b kwargs); if the argument count is anything other than 2 it throws this InvalidOperation error instead of proceeding. This is an argument-arity guard implemented by the library itself.","triggerScenarios":"Calling diff_of_two_dicts(a) with one dict, diff_of_two_dicts() with none, or diff_of_two_dicts(a, b, c) with three or more arguments. Any Jinja template in a dbt model/macro that passes the wrong number of positional args.","commonSituations":"Template refactors where a second dict argument was dropped or an extra one added; conditional template logic that supplies args dynamically and sometimes passes only one; misunderstanding that the function needs both dicts in a single call rather than one per call.","solutions":["Pass exactly two dict arguments: diff_of_two_dicts(dict_a, dict_b)","If one dict may be missing, guard with an if-block or pass an empty dict {} instead of omitting the argument","If using kwargs, supply both dict_a= and dict_b= together"],"exampleFix":"// before\n{% set diff = diff_of_two_dicts(my_dict) %}\n// after\n{% set diff = diff_of_two_dicts(my_dict, other_dict) %}","handlingStrategy":"validation","validationCode":"{% if dict_a is not defined or dict_b is not defined %}\n  {{ exceptions.raise_compiler_error('diff_of_two_dicts needs both dicts in ' ~ this) }}\n{% endif %}","typeGuard":"{% macro has_both_dicts(a, b) %}\n  {{ return(a is defined and b is defined and a is mapping and b is mapping) }}\n{% endmacro %}","tryCatchPattern":null,"preventionTips":["Always call diff_of_two_dicts with exactly two dict arguments","Count arguments when building calls dynamically in loops","Prefer kwarg form dict_a=/dict_b= to make omission visible"],"tags":["jinja","dbt","argument-count"],"backgroundTag":"missing-required-argument","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}