dbt-labs/dbt-core · error · minijinja::Error (InvalidOperation)

Column 'data_type' must be a string

Error message

Column 'data_type' must be a string

What it means

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.

Source

Thrown at crates/dbt-jinja-utils/src/functions/contract_error.rs:171

    match value.try_iter() {
        Ok(iter) => {
            for item in iter {
                let name_value = item.get_attr("name")?;
                let name = name_value
                    .as_str()
                    .ok_or_else(|| {
                        Error::new(
                            ErrorKind::InvalidOperation,
                            "Column 'name' must be a string",
                        )
                    })?
                    .to_string();

                let data_type_value = item.get_attr("data_type")?;
                let data_type = data_type_value
                    .as_str()
                    .ok_or_else(|| {
                        Error::new(
                            ErrorKind::InvalidOperation,
                            "Column 'data_type' must be a string",
                        )
                    })?
                    .to_string();

                let formatted = item
                    .get_attr("formatted")
                    .ok()
                    .and_then(|v| v.as_str().map(|s| s.to_string()));

                columns.push(ColumnDefinition {
                    name,
                    data_type,
                    formatted,
                });
            }
        }

View on GitHub (pinned to 0267ce9170)

Solutions

  1. 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).
  2. Inspect the adapter/macro producing the column objects and fix it to emit data_type as text, not a native value.
  3. Log the offending column object with |tojson to see the actual type and source of the bad value.

Example fix

// before (Rust-side or Jinja-side construction)
column.data_type = inferred_type; // e.g. minijinja value of type int
// after
column.data_type = inferred_type.as_str().unwrap_or_default().to_string();
Defensive patterns

Strategy: type-guard

Validate before calling

-- Jinja, before contract check
{% for col in columns %}
  {% if col.data_type is not string %}
    {{ exceptions.raise_compiler_error("column " ~ col.name ~ " data_type must be a string, got: " ~ col.data_type | tojson) }}
  {% endif %}
{% endfor %}

Type guard

fn is_string_attr(item: &MinijinjaValue, key: &str) -> bool {
    item.get_attr(key).ok().and_then(|v| v.as_str()).is_some()
}

Try / catch

match convert_value_to_column_definitions(value) {
    Err(e) if e.message().contains("'data_type' must be a string") => {
        // coerce or log column objects, then retry with stringified data_type
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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'.

Common situations: 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.

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/aa04b7694b0a2709. Report an issue: GitHub.