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
- Inspect the inner serde error appended to the message to find which field of the node failed to deserialize (missing field or wrong type).
- Pass the actual node object from the Jinja context (e.g. `model` in materialization context) rather than a manually constructed dict.
- Verify argument order: get_table_options(config, node, temporary=...) — ensure the node dict is the second positional argument.
- Update the dbt-fusion/dbt-adapter crate and templates together so node schema versions match.
- 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
- Always pass the node object from the materialization context (model), not hand-built dicts
- Keep templates and the adapter crate version-aligned
- Check argument order (config, node) when calling the macro
- Read the appended serde detail to diagnose field mismatches quickly
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
- get_view_options: Failed to deserialize InternalDbtNodeWrapp
- get_common_options: Failed to deserialize InternalDbtNodeWra
- {}
- compute_external_path: Failed to deserialize config: {e}
- compute_external_path: Failed to deserialize InternalDbtNode
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/1cc329c57f647251.
Report an issue: GitHub.