{"record":{"id":"1cc329c57f647251","repo":"dbt-labs/dbt-core","slug":"get-table-options-failed-to-deserialize-internald","errorCode":null,"errorMessage":"get_table_options: Failed to deserialize InternalDbtNodeWrapper: {e}","messagePattern":"get_table_options: Failed to deserialize InternalDbtNodeWrapper: (.+?)","errorType":"exception","errorClass":"minijinja::Error::SerdeDeserializeError","httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/adapter/mod.rs","lineNumber":2113,"sourceCode":"                let config_val = iter.next_arg::<&Value>()?;\n                let node_val = iter.next_arg::<&Value>()?;\n                let temporary = iter\n                    .next_kwarg::<Option<bool>>(\"temporary\")?\n                    .unwrap_or_default();\n                iter.finish()?;\n\n                let config = minijinja_value_to_typed_struct::<ModelConfig>(config_val.clone())\n                    .map_err(|e| {\n                        minijinja::Error::new(\n                            minijinja::ErrorKind::SerdeDeserializeError,\n                            format!(\"get_table_options: Failed to deserialize config: {e}\"),\n                        )\n                    })?;\n                let node = minijinja_value_to_typed_struct::<InternalDbtNodeWrapper>(\n                    node_val.clone(),\n                )\n                .map_err(|e| {\n                    minijinja::Error::new(\n                        minijinja::ErrorKind::SerdeDeserializeError,\n                        format!(\n                            \"get_table_options: Failed to deserialize InternalDbtNodeWrapper: {e}\"\n                        ),\n                    )\n                })?;\n\n                let options = adapter.get_table_options(state, config, &node, temporary)?;\n                Ok(Value::from_serialize(options))\n            }\n            Parse(_) => Ok(none_value()),\n        }\n    }\n\n    #[tracing::instrument(skip(self, state), level = \"trace\")]\n    pub fn get_view_options(\n        &self,\n        state: &State,","sourceCodeStart":2095,"sourceCodeEnd":2131,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/adapter/mod.rs#L2095-L2131","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (Jinja macro)\n{% do adapter.get_table_options(config.model, {}) %}\n\n// after\n{% do adapter.get_table_options(config.model, model) %}","handlingStrategy":"validation","validationCode":"// Jinja guard before the call\n{% if model is mapping and model.get('unique_id') is defined %}\n  {% do adapter.get_table_options(config.model, model) %}\n{% else %}\n  {{ exceptions.raise_compiler_error(\"get_table_options requires a valid node object\") }}\n{% endif %}","typeGuard":"fn is_node(val: &minijinja::Value) -> bool {\n    minijinja_value_to_typed_struct::<InternalDbtNodeWrapper>(val.clone()).is_ok()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["deserialization","jinja","adapter"],"backgroundTag":"schema-validation-failed","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}