dbt-labs/dbt-core · error · minijinja::Error::SerdeDeserializeError

model_columns: {e}

Error message

model_columns: {e}

What it means

parse_columns_and_constraints deserializes the model_columns argument into a BTreeMap<String, DbtColumn> (and then model constraints into Vec<ModelConstraint>). Any serde failure is wrapped in a SerdeDeserializeError prefixed with 'model_columns:'. This validates that the model's column definitions match the expected struct shape before constraint parsing.

Source

Thrown at crates/dbt-adapter/src/adapter/adapter_impl.rs:4669

            .map_err(|e| {
                minijinja::Error::new(
                    minijinja::ErrorKind::InvalidOperation,
                    format!("existing_columns must be iterable: {e}"),
                )
            })?
            .map(|v| {
                v.downcast_object_ref::<Column>().cloned().ok_or_else(|| {
                    minijinja::Error::new(
                        minijinja::ErrorKind::InvalidOperation,
                        "existing_columns must contain Column objects",
                    )
                })
            })
            .collect::<Result<Vec<_>, _>>()?;

        let model_columns_map: BTreeMap<String, DbtColumn> =
            minijinja_value_to_typed_struct(model_columns.clone()).map_err(|e| {
                minijinja::Error::new(
                    minijinja::ErrorKind::SerdeDeserializeError,
                    format!("model_columns: {e}"),
                )
            })?;

        let model_constraints_vec: Vec<ModelConstraint> =
            minijinja_value_to_typed_struct(model_constraints.clone()).map_err(|e| {
                minijinja::Error::new(
                    minijinja::ErrorKind::SerdeDeserializeError,
                    format!("model_constraints: {e}"),
                )
            })?;

        let column_refs: Vec<DbtColumnRef> = model_columns_map
            .values()
            .map(|c| Arc::new(c.clone()))
            .collect();

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Read the text after 'model_columns:' in the error — it names the failing field — and fix the config.
  2. Pass model.columns as a name -> column map with standard dbt column fields.
  3. Ensure model constraints follow the documented ModelConstraint structure (name/type/expr etc.).
  4. Avoid transforming model.columns in custom macros before calling this API.

Example fix

// before
model_columns = [("id", "int")]  # list of tuples
adapter.parse_columns_and_constraints(existing, model_columns, name)

// after
model_columns = {"id": {"name": "id", "data_type": "int"}}
adapter.parse_columns_and_constraints(existing, model_columns, name)
Defensive patterns

Strategy: validation

Validate before calling

def is_model_column_map(v):
    return isinstance(v, dict) and all(
        isinstance(k, str) and isinstance(c, dict) and 'name' in c
        for k, c in v.items())

Type guard

def as_model_columns(v):
    return v if is_model_column_map(v) else None

Try / catch

try:
    parsed = adapter.parse_columns_and_constraints(existing, model_columns, name)
except Exception as e:
    if str(e).startswith('model_columns:'):
        raise ValueError(f'model.columns shape invalid: {e}') from e
    raise

Prevention

When it happens

Trigger: Calling parse_columns_and_constraints with model_columns that cannot deserialize into IndexMap/BTreeMap<String, DbtColumn>: list instead of map, entries missing required DbtColumn fields, or wrong-typed fields.

Common situations: Passing model.config.columns in an unusual shape; custom materializations that reshape columns before this call; constraints defined with unexpected keys in model config; schema.yml columns with nonstandard metadata keys mapped into the column struct.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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