{"record":{"id":"81cb7b05fdbc9c49","repo":"dbt-labs/dbt-core","slug":"expected-a-list-of-column-definitions","errorCode":null,"errorMessage":"Expected a list of column definitions","messagePattern":"Expected a list of column definitions","errorType":"validation","errorClass":"minijinja::Error (InvalidOperation)","httpStatus":null,"severity":"error","filePath":"crates/dbt-jinja-utils/src/functions/contract_error.rs","lineNumber":191,"sourceCode":"                            \"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        }\n        Err(_) => {\n            return Err(Error::new(\n                ErrorKind::InvalidOperation,\n                \"Expected a list of column definitions\",\n            ));\n        }\n    }\n\n    Ok(columns)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use dbt_agate::MappedSequence;\n\n    #[test]\n    fn test_contract_error_perfect_match() {\n        let yaml_columns = vec![\n            ColumnDefinition {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-jinja-utils/src/functions/contract_error.rs#L173-L209","documentation":"Thrown by convert_value_to_column_definitions when the value it is iterating is not a list of column definitions. The contract mismatch logic only accepts a sequence whose items are objects with attributes like name/data_type; anything else (e.g. a plain string, dict-of-dicts, or non-sequence) falls into the Err arm of the iterator conversion and aborts.","triggerScenarios":"get_contract_mismatches receives a 'columns' value that is not a list (e.g. a mapping, a single object, or a string), or list items are not objects with column attributes, causing the minijinja iteration/attribute extraction to fail.","commonSituations":"Passing a dict keyed by column name instead of a list of column dicts; macros returning a single column instead of a list; whitespace/formatting changes in rendered macro output producing malformed results; version drift between custom contract macros and the engine.","solutions":["Make sure the columns value passed to contract checking is a list (Jinja array) of column objects each with name and data_type attributes.","If your columns are a mapping, convert to a list of objects (e.g. [{'name': k, 'data_type': v} ...]).","Print the value with |tojson before the call to confirm its shape."],"exampleFix":"-- before (Jinja)\n{% do contract_check(columns={'id': 'int', 'name': 'text'}) %}\n-- after\n{% do contract_check(columns=[{'name': 'id', 'data_type': 'int'}, {'name': 'name', 'data_type': 'text'}]) %}","handlingStrategy":"validation","validationCode":"-- Jinja, before contract check\n{% if columns is not sequence or columns is string or columns is mapping %}\n  {{ exceptions.raise_compiler_error(\"columns must be a list of column definitions, got: \" ~ columns | tojson) }}\n{% endif %}","typeGuard":null,"tryCatchPattern":"match convert_value_to_column_definitions(value) {\n    Err(e) if e.message().contains(\"Expected a list of column definitions\") => {\n        // dump value with |tojson, fix shape to a list of objects\n    }\n    other => other?,\n}","preventionTips":["Standardize on a list of {name, data_type} dicts for all contract-check macros.","Convert name-keyed column mappings to lists before checking contracts.","Snapshot macro output with |tojson in tests to catch shape regressions."],"tags":["schema-validation","jinja","contract-testing","dbt"],"backgroundTag":"schema-validation-failed","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"}