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

  1. Build each list element as a Column object (Column.from_description(...) or Column.create(...)) instead of a plain dict or string.
  2. If you start from dicts, convert each item with Column.from_jinja_value / from a DbtCoreBaseColumn first.
  3. Check the source of the list — results of a JSON round-trip or `to_value()` on plain data will not be Column objects.
  4. 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

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


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/47d23a36e8d99a82. Report an issue: GitHub.