{"record":{"id":"75869f4df7f3bf5a","repo":"dbt-labs/dbt-core","slug":"invalid-config-object-specified-keys-must-be-stri","errorCode":null,"errorMessage":"Invalid config object specified. Keys must be strings","messagePattern":"Invalid config object specified\\. Keys must be strings","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-jinja-utils/src/phases/parse/resolve_model_context.rs","lineNumber":813,"sourceCode":"            let positional_val: MinijinjaValue = args.next_positional::<MinijinjaValue>()?;\n            if positional_val.kind() != ValueKind::Map {\n                return Err(MinijinjaError::new(\n                    MinijinjaErrorKind::InvalidOperation,\n                    format!(\n                        \"Invalid config argument kind specified: {}\",\n                        positional_val.kind()\n                    ),\n                ));\n            }\n            positional_val\n                .as_object()\n                .unwrap()\n                .try_iter_pairs()\n                .expect(\"Invalid config object specified\")\n                .map(|(k, v)| {\n                    (\n                        k.as_str()\n                            .expect(\"Invalid config object specified. Keys must be strings\")\n                            .to_string(),\n                        v,\n                    )\n                })\n                .collect()\n        } else {\n            args.drain_kwargs()\n        };\n\n        self.apply_config(state, kwargs)\n    }\n\n    fn call_method(\n        self: &Arc<Self>,\n        state: &State<'_, '_>,\n        name: &str,\n        args: &[MinijinjaValue],\n        _listeners: &[Rc<dyn RenderingEventListener>],","sourceCodeStart":795,"sourceCodeEnd":831,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-jinja-utils/src/phases/parse/resolve_model_context.rs#L795-L831","documentation":"Companion check to the pair-iteration panic: after successfully iterating the config object's pairs, each key is narrowed to a string with `as_str()` and unwrapped with `expect`. The panic fires when a key in the config dict is not a string (e.g. an integer or boolean key). dbt config keys must be strings to be merged into node config.","triggerScenarios":"Calling `{{ config({...}) }}` where the dict has non-string keys, most commonly `{{ config({1: 'value'}) }}` or keys produced by macros using non-string literals; also YAML-injected configs with numeric keys round-tripped into jinja.","commonSituations":"Programmatic config generation in jinja using numeric keys; quoting mistakes turning keys into numbers; users writing `{{ config({'2024_tags': ...}) }}` vs `{{ config({2024: ...}) }}` style dicts.","solutions":["Quote all keys in the config dict: `{{ config({'key': 'value'}) }}` instead of `{{ config({key: 'value'}) }}` with a numeric key","Convert keys to strings in the macro that builds the config (`key ~ ''` or `key|string`)","Audit the failing model's config calls for numeric/boolean keys","At the code level, replace expect with an error that shows the offending key and its type"],"exampleFix":"// before (model.sql)\n{{ config({1: 'priority'}) }}\n// after\n{{ config({'1': 'priority'}) }}","handlingStrategy":"validation","validationCode":"{% for k in cfg.keys() %}\n  {% if k is not string %}\n    {{ exceptions.raise_compiler_error(\"config keys must be strings, got: \" ~ type(k)) }}\n  {% endif %}\n{% endfor %}","typeGuard":"// in jinja, coerce keys before building the dict\n{% set cfg = {} %}\n{% do cfg.update({k|string: v}) %}","tryCatchPattern":"k.as_str().ok_or_else(|| MinijinjaError::new(\n    ErrorKind::InvalidOperation,\n    format!(\"config keys must be strings, got: {k:?}\")))?;","preventionTips":["Always quote dict keys in {{ config({...}) }} calls","Coerce dynamic keys with `|string` in macros that build configs","Avoid numeric literals as config keys","Lint models for config dicts with unquoted keys"],"tags":["panic","config","jinja","type-mismatch","keys"],"backgroundTag":"type-mismatch","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"}