dbt-labs/dbt-core · error · InvalidOperation
Failed to convert value to JSON: {err}
Error message
Failed to convert value to JSON: {err} What it means
The tojson Jinja filter serializes a value to a Python-style JSON string. When the underlying conversion to a serde_json value fails and no default argument was supplied, this InvalidOperation error is raised carrying the serialization error message. With a default provided, the default is returned instead.
Source
Thrown at crates/dbt-jinja-utils/src/functions/base.rs:477
Ok(mut json_value) => {
if sort_keys && let Some(obj) = json_value.as_object_mut() {
// Sort the keys using BTreeMap
let sorted: serde_json::Map<String, serde_json::Value> = obj
.iter()
.collect::<BTreeMap<_, _>>()
.into_iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
json_value = serde_json::Value::Object(sorted);
}
// Use Python-style formatting (space after colon)
let json_str =
to_json_string_python_style(&json_value).unwrap_or_else(|_| "{}".to_string());
Ok(Value::from_safe_string(json_str))
}
Err(err) => match default {
Some(default_value) => Ok(default_value.clone()),
None => Err(Error::new(
ErrorKind::InvalidOperation,
format!("Failed to convert value to JSON: {err}"),
)),
},
}
}
/// Deserialize a YAML string into a Python object primitive.
///
/// ```python
/// def fromyaml(value: str, default: Any = None) -> Any:
/// """The fromyaml context method can be used to deserialize a yaml string
/// into a Python object primitive, eg. a `dict` or `list`.
///
/// :param value: The yaml string to deserialize
/// :param default: A default value to return if the `string` argument
/// cannot be deserialized (optional)
///View on GitHub (pinned to 0267ce9170)
Solutions
- Pass a default: {{ value | tojson(default='{}') }} to fall back on serialization failure.
- Ensure the value is plain data (dict/list/scalar) before piping to tojson.
- Guard with is defined / is mapping tests before serializing.
- If serializing a dbt relation or object, serialize its serializable attributes instead.
Example fix
// before
{{ config_obj | tojson }}
// after
{{ config_obj | tojson(default='{}') }} Defensive patterns
Strategy: fallback
Validate before calling
{% if value is defined and (value is mapping or value is sequence or value is string) %}...{% endif %} Try / catch
{{ value | tojson(default='{}') }} // graceful fallback inside the filter Prevention
- Always pass a default to tojson for user-controlled values.
- Only pipe plain data structures into tojson.
- Validate context values are defined before serialization.
When it happens
Trigger: {{ value | tojson }} where value is not JSON-serializable (cyclic structure, non-string map keys that can't convert, or an opaque minijinja value), and no default parameter is passed.
Common situations: Serializing undefined or exotic objects from context, dumping results of macros that return unsupported types, or templates that relied on implicit coercion.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- get_csv_data: failed to format CSV: {e}
- {}
- Failed to convert value to YAML: {err}
- Failed to serialize core event info to JSON
- Failed to serialize merged node config to dbt_yaml::Value fo
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/84b545ffaf3c1f48.
Report an issue: GitHub.