dbt-labs/dbt-core · error
Failed to downcast jinja value to Column; expected Column ob
Error message
Failed to downcast jinja value to Column; expected Column object
What it means
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.
Source
Thrown at crates/dbt-adapter/src/column/types.rs:648
) -> Result<Self, minijinja::Error> {
let core_col =
minijinja_value_to_typed_struct::<DbtCoreBaseColumn>(value).map_err(|e| {
minijinja::Error::new(minijinja::ErrorKind::SerdeDeserializeError, e.to_string())
})?;
Ok(Self::from_dbt_core(adapter_type, core_col))
}
pub fn vec_from_jinja_value(
_adapter_type: AdapterType,
value: Value,
) -> Result<Vec<Self>, minijinja::Error> {
// Iterate over the jinja value which should be a sequence
value
.try_iter()?
.map(|item| {
item.downcast_object_ref::<Self>().cloned().ok_or_else(|| {
minijinja::Error::new(
minijinja::ErrorKind::InvalidOperation,
"Failed to downcast jinja value to Column; expected Column object",
)
})
})
.collect()
}
/// Create a new BigQuery column
///
/// `mode` ias a field is seen in BQ (https://cloud.google.com/bigquery/docs/schemas#modes)
pub fn new_bigquery(
name: String,
original_sql_str: String,
fields: impl Into<Vec<Self>>,
mode: BigqueryColumnMode,
) -> Self {
use BigqueryColumnMode::*;View on GitHub (pinned to 0267ce9170)
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.
Example fix
// before (Jinja)
{% set cols = [{'name': 'id', 'dtype': 'INT'}] %}
{% set sql = Column.format_add_column_list(columns=cols) %}
// after
{% set cols = [Column.from_description(name='id', raw_data_type='INT')] %}
{% set sql = Column.format_add_column_list(columns=cols) %} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: verify each item downcasts to Column before collecting
fn all_are_columns(value: &minijinja::Value) -> bool {
value.clone().try_iter().map(|it| {
it.all(|item| item.downcast_object_ref::<crate::column::types::Column>().is_some())
}).unwrap_or(false)
} Type guard
fn is_column_object(v: &minijinja::Value) -> bool {
v.downcast_object_ref::<crate::column::types::Column>().is_some()
} Try / catch
match Column::vec_from_jinja_value(at, value) {
Ok(cols) => cols,
Err(e) if e.to_string().contains("Failed to downcast") => {
eprintln!("list items must be Column objects, got other values");
Vec::new()
}
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- {}
- existing_columns must contain Column objects
- Unknown method on ColumnStatic: '{name}'
- {msg}
- render_constraints_for_create is only available for Databric
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/47d23a36e8d99a82.
Report an issue: GitHub.