dbt-labs/dbt-core · error · InvalidOperation

Failed to convert value to YAML: {err}

Error message

Failed to convert value to YAML: {err}

What it means

The toyaml Jinja filter first converts its input Minijinja Value into a serde_json::Value as an intermediate representation. If that conversion fails, this InvalidOperation error is raised (the message says YAML but the failure is in the JSON conversion step).

Source

Thrown at crates/dbt-jinja-utils/src/functions/base.rs:577

    let sort_keys = iter
        .next_kwarg::<Option<bool>>("sort_keys")?
        .unwrap_or(false);

    // If the value is undefined or none and there's a default, return it
    if value.is_undefined() || value.is_none() {
        return match default {
            Some(def) => Ok(def.clone()),
            // Return none for undefined/none values when no default is provided
            None => Ok(Value::from(())),
        };
    }

    // Convert the Minijinja Value to a serde_json::Value
    // Should this say YAML or JSON cause this is toyaml function, not sure
    let mut json_value = match serde_json::to_value(value) {
        Ok(val) => val,
        Err(err) => {
            return Err(Error::new(
                ErrorKind::InvalidOperation,
                format!("Failed to convert value to YAML: {err}"),
            ));
        }
    };

    // Sort keys if requested
    if sort_keys && let Some(obj) = json_value.as_object_mut() {
        let sorted_map: BTreeMap<_, _> = obj.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
        *obj = sorted_map.into_iter().collect();
    }

    match dbt_yaml::to_string(&json_value) {
        Ok(yaml_str) => Ok(Value::from(yaml_str)),
        Err(err) => Err(Error::new(
            ErrorKind::InvalidOperation,
            format!("Failed to convert value to YAML: {err}"),
        )),

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Ensure the input is plain data (mappings, sequences, scalars) before piping to toyaml.
  2. Guard the variable with is defined / is mapping before conversion.
  3. Serialize only plain attributes of complex objects.
  4. Read the inner err message to identify which value component failed conversion.

Example fix

// before
{{ undefined_var | toyaml }}
// after
{% if undefined_var is defined %}{{ undefined_var | toyaml }}{% endif %}
Defensive patterns

Strategy: validation

Validate before calling

{% if value is not defined %}{% do exceptions.raise_compiler_error('toyaml input undefined') %}{% endif %}

Try / catch

{% if value is defined and value is mapping %}{{ value | toyaml }}{% else %}{}{% endif %}

Prevention

When it happens

Trigger: {{ value | toyaml }} where the Minijinja value cannot be converted to a serde_json value (unsupported/opaque types, cyclic or non-representable structures).

Common situations: Piping undefined variables or objects (e.g. relations, macros results) into toyaml; templates expecting implicit coercion of exotic types.

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


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/1a28f47e296f34ea. Report an issue: GitHub.