{"record":{"id":"aa04b7694b0a2709","repo":"dbt-labs/dbt-core","slug":"column-data-type-must-be-a-string","errorCode":null,"errorMessage":"Column 'data_type' must be a string","messagePattern":"Column 'data_type' must be a string","errorType":"validation","errorClass":"minijinja::Error (InvalidOperation)","httpStatus":null,"severity":"error","filePath":"crates/dbt-jinja-utils/src/functions/contract_error.rs","lineNumber":171,"sourceCode":"    match value.try_iter() {\n        Ok(iter) => {\n            for item in iter {\n                let name_value = item.get_attr(\"name\")?;\n                let name = name_value\n                    .as_str()\n                    .ok_or_else(|| {\n                        Error::new(\n                            ErrorKind::InvalidOperation,\n                            \"Column 'name' must be a string\",\n                        )\n                    })?\n                    .to_string();\n\n                let data_type_value = item.get_attr(\"data_type\")?;\n                let data_type = data_type_value\n                    .as_str()\n                    .ok_or_else(|| {\n                        Error::new(\n                            ErrorKind::InvalidOperation,\n                            \"Column 'data_type' must be a string\",\n                        )\n                    })?\n                    .to_string();\n\n                let formatted = item\n                    .get_attr(\"formatted\")\n                    .ok()\n                    .and_then(|v| v.as_str().map(|s| s.to_string()));\n\n                columns.push(ColumnDefinition {\n                    name,\n                    data_type,\n                    formatted,\n                });\n            }\n        }","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-jinja-utils/src/functions/contract_error.rs#L153-L189","documentation":"Thrown by convert_value_to_column_definitions when building contract column definitions: the Jinja object's 'data_type' attribute exists but its value is not a string (minijinja value fails as_str()). The library needs a plain string data type to compare model contracts against actual column definitions, so it refuses any other value type rather than coercing silently.","triggerScenarios":"A column object passed into get_contract_mismatches has a 'data_type' attribute that is a non-string minijinja value (e.g. an integer, dict, list, or undefined-ish object) instead of a string like 'varchar'.","commonSituations":"Custom materializations or macros that build contract check results programmatically and set data_type from numeric/config values; adapters returning column metadata with typed values instead of strings; hand-rolled contract test code populating data_type with a dict or number.","solutions":["Ensure the 'data_type' attribute of each column object is a string before invoking contract mismatch checking (coerce with ~ or |string in Jinja, or .to_string() in Rust).","Inspect the adapter/macro producing the column objects and fix it to emit data_type as text, not a native value.","Log the offending column object with |tojson to see the actual type and source of the bad value."],"exampleFix":"// before (Rust-side or Jinja-side construction)\ncolumn.data_type = inferred_type; // e.g. minijinja value of type int\n// after\ncolumn.data_type = inferred_type.as_str().unwrap_or_default().to_string();","handlingStrategy":"type-guard","validationCode":"-- Jinja, before contract check\n{% for col in columns %}\n  {% if col.data_type is not string %}\n    {{ exceptions.raise_compiler_error(\"column \" ~ col.name ~ \" data_type must be a string, got: \" ~ col.data_type | tojson) }}\n  {% endif %}\n{% endfor %}","typeGuard":"fn is_string_attr(item: &MinijinjaValue, key: &str) -> bool {\n    item.get_attr(key).ok().and_then(|v| v.as_str()).is_some()\n}","tryCatchPattern":"match convert_value_to_column_definitions(value) {\n    Err(e) if e.message().contains(\"'data_type' must be a string\") => {\n        // coerce or log column objects, then retry with stringified data_type\n    }\n    other => other?,\n}","preventionTips":["Always build contract column data_type via |string in Jinja macros.","Add a unit test feeding contract-check helpers a non-string data_type.","Keep adapter column metadata conversion in one place that guarantees strings."],"tags":["type-mismatch","jinja","contract-testing","dbt"],"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"}