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

get_table_options: Failed to deserialize InternalDbtNodeWrap

Error message

get_table_options: Failed to deserialize InternalDbtNodeWrapper: {e}

What it means

get_table_options() is exposed to Jinja macros and expects its `node` argument to be a Value that can be converted into an InternalDbtNodeWrapper struct. When the minijinja Value passed as the node does not match the expected struct schema (missing/wrongly-typed fields such as common metadata, config, etc.), the serde deserialization fails and this error is raised with the underlying serde message appended. It indicates the caller (usually a macro) passed something other than a valid dbt node object.

Source

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

                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))
            }
            Parse(_) => Ok(none_value()),
        }
    }

    #[tracing::instrument(skip(self, state), level = "trace")]
    pub fn get_view_options(
        &self,
        state: &State,

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Inspect the inner serde error appended to the message to find which field of the node failed to deserialize (missing field or wrong type).
  2. Pass the actual node object from the Jinja context (e.g. `model` in materialization context) rather than a manually constructed dict.
  3. Verify argument order: get_table_options(config, node, temporary=...) — ensure the node dict is the second positional argument.
  4. Update the dbt-fusion/dbt-adapter crate and templates together so node schema versions match.
  5. If constructing nodes in tests, build them via InternalDbtNodeWrapper serialization rather than ad-hoc dicts.

Example fix

// before (Jinja macro)
{% do adapter.get_table_options(config.model, {}) %}

// after
{% do adapter.get_table_options(config.model, model) %}
Defensive patterns

Strategy: validation

Validate before calling

// Jinja guard before the call
{% if model is mapping and model.get('unique_id') is defined %}
  {% do adapter.get_table_options(config.model, model) %}
{% else %}
  {{ exceptions.raise_compiler_error("get_table_options requires a valid node object") }}
{% 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: Calling adapter.get_table_options(config, node) from Jinja with a node argument that is a dict missing required InternalDbtNodeWrapper fields, a string/number instead of a node object, a materialization-passed object of an unexpected shape, or after an internal schema change where the node dict no longer deserializes.

Common situations: Custom materializations or macros calling get_table_options with a hand-built node dict; a dbt version mismatch where the node schema changed; passing config-model values into the node slot by argument-order mistake; debugging scripts that fabricate node objects.

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