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

get_table_options: Failed to deserialize config: {e}

Error message

get_table_options: Failed to deserialize config: {e}

What it means

`get_table_options` deserializes the `config` argument into `ModelConfig` and, unlike the other call sites, prefixes the serde failure with `get_table_options: Failed to deserialize config:` as a minijinja `SerdeDeserializeError`. It means the model config object passed from Jinja does not conform to the ModelConfig struct the adapter expects.

Source

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

    #[tracing::instrument(skip(self, state), level = "trace")]
    pub fn get_table_options(
        &self,
        state: &State,
        args: &[Value],
    ) -> Result<Value, minijinja::Error> {
        match &self.inner {
            Typed { adapter, .. } => {
                let iter = ArgsIter::new("get_table_options", &["config", "node"], args);
                let config_val = iter.next_arg::<&Value>()?;
                let node_val = iter.next_arg::<&Value>()?;
                let temporary = iter
                    .next_kwarg::<Option<bool>>("temporary")?
                    .unwrap_or_default();
                iter.finish()?;

                let config = minijinja_value_to_typed_struct::<ModelConfig>(config_val.clone())
                    .map_err(|e| {
                        minijinja::Error::new(
                            minijinja::ErrorKind::SerdeDeserializeError,
                            format!("get_table_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_table_options: Failed to deserialize InternalDbtNodeWrapper: {e}"
                        ),
                    )
                })?;

                let options = adapter.get_table_options(state, config, &node, temporary)?;
                Ok(Value::from_serialize(options))

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Read the prefixed message to identify the exact field/type mismatch.
  2. Pass the model's real `config` object (e.g. `model.config`) rather than a reconstructed dict.
  3. Remove or fix keys with wrong types in the config (quote strings, use booleans for flags).
  4. Diff the config against the adapter's ModelConfig fields for the installed version.
  5. Update custom materializations/macros to the current adapter API.

Example fix

// before (Jinja)
{% set opts = adapter.get_table_options(config={'k': 'v'}, node=node) %}
// after
{% set opts = adapter.get_table_options(config=model.config, node=node) %}
Defensive patterns

Strategy: validation

Validate before calling

{# Jinja #}
{% if config is not mapping %}
  {{ exceptions.raise_compiler_error('get_table_options requires a config mapping') }}
{% endif %}
{% set opts = adapter.get_table_options(config=model.config, node=node) %}

Type guard

fn is_model_config(v: &minijinja::Value) -> bool {
    minijinja_value_to_typed_struct::<ModelConfig>(v.clone()).is_ok()
}

Try / catch

{% try %}
  {% set opts = adapter.get_table_options(config=cfg, node=node) %}
{% except %}
  {{ log('get_table_options config invalid: ' ~ cfg | tojson, info=true) }}
{% endtry %}

Prevention

When it happens

Trigger: Calling `adapter.get_table_options(config=<value>, node=..., temporary=...)` where config is a plain dict missing required ModelConfig fields or containing keys/values of the wrong type.

Common situations: Custom materialization macros passing a hand-built config dict instead of the node's `config` object; project vars injecting unexpected keys; adapter version changes to ModelConfig fields breaking older macros.

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