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

get_common_options: Failed to deserialize InternalDbtNodeWra

Error message

get_common_options: Failed to deserialize InternalDbtNodeWrapper: {e}

What it means

Raised by get_common_options() when the `node` argument fails to deserialize into InternalDbtNodeWrapper. The macro needs node metadata (relation info, config, resource type) to compute common options, so a non-conforming node value aborts with this SerdeDeserializeError and the serde reason appended.

Source

Thrown at crates/dbt-adapter/src/adapter/mod.rs:2195

                let config_val = iter.next_arg::<&Value>()?;
                let node_val = iter.next_arg::<&Value>()?;
                let temporary = iter
                    .next_kwarg::<Option<bool>>("temporary")?
                    .unwrap_or(false);
                iter.finish()?;

                let config = minijinja_value_to_typed_struct::<ModelConfig>(config_val.clone())
                    .map_err(|e| {
                        minijinja::Error::new(
                            minijinja::ErrorKind::SerdeDeserializeError,
                            format!("get_common_options: Failed to deserialize config: {e}"),
                        )
                    })?;
                let node = minijinja_value_to_typed_struct::<InternalDbtNodeWrapper>(
                    node_val.clone(),
                )
                .map_err(|e| {
                    minijinja::Error::new(
                        minijinja::ErrorKind::SerdeDeserializeError,
                        format!(
                            "get_common_options: Failed to deserialize InternalDbtNodeWrapper: {e}"
                        ),
                    )
                })?;

                let options = adapter.get_common_options(state, config, &node, temporary)?;
                Ok(options)
            }
            Parse(_) => Ok(none_value()),
        }
    }

    /// Add time ingestion partition column
    ///
    /// https://github.com/dbt-labs/dbt-adapters/blob/main/dbt-bigquery/src/dbt/adapters/bigquery/impl.py#L259
    ///

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Inspect the appended serde error for the missing or mistyped node field.
  2. Pass the real node object (e.g. `model` in a materialization) as the second argument.
  3. If building nodes programmatically, serialize a full InternalDbtNodeWrapper rather than a partial dict.
  4. Update templates and adapter together to avoid schema drift.

Example fix

// before
{% set opts = adapter.get_common_options(config.model, none) %}

// after
{% set opts = adapter.get_common_options(config.model, model) %}
Defensive patterns

Strategy: validation

Validate before calling

{% if model is mapping and model.get('unique_id') is defined %}
  {% set opts = adapter.get_common_options(config.model, model) %}
{% endif %}

Type guard

fn is_node(val: &minijinja::Value) -> bool {
    minijinja_value_to_typed_struct::<InternalDbtNodeWrapper>(val.clone()).is_ok()
}

Prevention

When it happens

Trigger: adapter.get_common_options(config, node, temporary=...) invoked with node = None, a scalar, a relation object, or a dict missing required InternalDbtNodeWrapper fields (e.g. after schema changes or hand-crafted test nodes).

Common situations: Custom incremental/table materializations passing the wrong context variable for node; partial node dicts in tests; version mismatch between templates and adapter crate.

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