{"record":{"id":"47d23a36e8d99a82","repo":"dbt-labs/dbt-core","slug":"failed-to-downcast-jinja-value-to-column-expected","errorCode":null,"errorMessage":"Failed to downcast jinja value to Column; expected Column object","messagePattern":"Failed to downcast jinja value to Column; expected Column object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/column/types.rs","lineNumber":648,"sourceCode":"    ) -> Result<Self, minijinja::Error> {\n        let core_col =\n            minijinja_value_to_typed_struct::<DbtCoreBaseColumn>(value).map_err(|e| {\n                minijinja::Error::new(minijinja::ErrorKind::SerdeDeserializeError, e.to_string())\n            })?;\n\n        Ok(Self::from_dbt_core(adapter_type, core_col))\n    }\n\n    pub fn vec_from_jinja_value(\n        _adapter_type: AdapterType,\n        value: Value,\n    ) -> Result<Vec<Self>, minijinja::Error> {\n        // Iterate over the jinja value which should be a sequence\n        value\n            .try_iter()?\n            .map(|item| {\n                item.downcast_object_ref::<Self>().cloned().ok_or_else(|| {\n                    minijinja::Error::new(\n                        minijinja::ErrorKind::InvalidOperation,\n                        \"Failed to downcast jinja value to Column; expected Column object\",\n                    )\n                })\n            })\n            .collect()\n    }\n\n    /// Create a new BigQuery column\n    ///\n    /// `mode` ias a field is seen in BQ (https://cloud.google.com/bigquery/docs/schemas#modes)\n    pub fn new_bigquery(\n        name: String,\n        original_sql_str: String,\n        fields: impl Into<Vec<Self>>,\n        mode: BigqueryColumnMode,\n    ) -> Self {\n        use BigqueryColumnMode::*;","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/column/types.rs#L630-L666","documentation":"Column::vec_from_jinja_value expects a Jinja sequence whose items are already Column objects (Rust Column instances exposed to Jinja). Each item is downcast via downcast_object_ref::<Column>; any item that is not a native Column object — e.g. a plain dict, string, or a DbtCoreBaseColumn proxy — fails the downcast and raises this InvalidOperation error. It does not attempt conversion; only genuine Column objects are accepted.","triggerScenarios":"Calling ColumnStatic.format_add_column_list(columns=...) or format_remove_column_list(columns=...) where `columns` is a list of dicts/strings/other objects rather than a list of Column instances created via Column.create/from_description/from_jinja_value; also passing a non-iterable value (try_iter fails first with its own error).","commonSituations":"Databricks ALTER TABLE macros (add/remove column list) fed raw column name strings; lists built by deserializing JSON so items became dicts instead of Column objects; mixing Column objects with plain dicts in one list.","solutions":["Build each list element as a Column object (Column.from_description(...) or Column.create(...)) instead of a plain dict or string.","If you start from dicts, convert each item with Column.from_jinja_value / from a DbtCoreBaseColumn first.","Check the source of the list — results of a JSON round-trip or `to_value()` on plain data will not be Column objects.","In Rust-side tests, use Value::from_object(Column::...) when constructing the sequence."],"exampleFix":"// before (Jinja)\n{% set cols = [{'name': 'id', 'dtype': 'INT'}] %}\n{% set sql = Column.format_add_column_list(columns=cols) %}\n// after\n{% set cols = [Column.from_description(name='id', raw_data_type='INT')] %}\n{% set sql = Column.format_add_column_list(columns=cols) %}","handlingStrategy":"type-guard","validationCode":"// Rust: verify each item downcasts to Column before collecting\nfn all_are_columns(value: &minijinja::Value) -> bool {\n    value.clone().try_iter().map(|it| {\n        it.all(|item| item.downcast_object_ref::<crate::column::types::Column>().is_some())\n    }).unwrap_or(false)\n}","typeGuard":"fn is_column_object(v: &minijinja::Value) -> bool {\n    v.downcast_object_ref::<crate::column::types::Column>().is_some()\n}","tryCatchPattern":"match Column::vec_from_jinja_value(at, value) {\n    Ok(cols) => cols,\n    Err(e) if e.to_string().contains(\"Failed to downcast\") => {\n        eprintln!(\"list items must be Column objects, got other values\");\n        Vec::new()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only pass Column instances (from create/from_description/from_jinja_value) into format_add_column_list / format_remove_column_list.","Never round-trip Column lists through JSON/serialization before passing them back to Jinja APIs.","Pre-check each item with a downcast in debug/test code.","In Databricks ALTER macros, construct the column list from Column.from_description calls, not name strings."],"tags":["jinja","adapter","column","downcast","databricks"],"backgroundTag":"type-mismatch","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}