BoundaryML/baml · error

baml.json.serialize failed: {e:?}

Error message

baml.json.serialize failed: {e:?}

What it means

This error is produced by serialize_via_baml_json in the BAML executor when the `baml.json` external function fails while serializing a value (typically a class/object) to a JSON string. The call to the baml.json function is awaited and any failure from it is wrapped with anyhow! with the underlying error debug-formatted. It exists to carry the nested evaluation error into the output-writing pipeline (write_output_with_context) with a clear origin prefix.

Source

Thrown at baml_language/crates/baml_exec/src/output.rs:109

/// runtime-value dispatch honors user `baml.ToJson` overrides at every depth.
async fn serialize_via_baml_json(
    engine: &Arc<BexEngine>,
    value: BexExternalValue,
    return_type: &RuntimeTy,
    helper_context: &HelperCallContext,
) -> Result<String> {
    let result = engine
        .call_function(
            "baml.json.serialize",
            vec![value],
            helper_context.call_context(indexmap::IndexMap::from([(
                "T".to_string(),
                return_type.clone(),
            )])),
            true,
        )
        .await
        .map_err(|e| anyhow!("baml.json.serialize failed: {e:?}"))?;
    match result {
        BexExternalValue::String(s) => Ok(s.to_string()),
        other => Err(anyhow!(
            "baml.json.serialize returned non-string value: {other:?}"
        )),
    }
}

/// Human-readable formatting for `BexExternalValue`.
///
/// Thin wrapper over [`BexExternalValue::render_readable`] — the canonical
/// structural renderer, shared with the engine's uncaught-throw rendering so
/// `baml run` output and a leaked `throw` render identically.
pub fn format_value(value: &BexExternalValue) -> String {
    value.render_readable()
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the wrapped `{e:?}` payload to identify the underlying baml.json evaluation failure and fix the value/type it complains about
  2. Verify the value being serialized matches the declared return_type (e.g. class field types) before calling the output writer
  3. Check that the LLM response is valid and the function's output schema compiles/evaluates correctly (run `baml test` / inspect intermediate result)
  4. Upgrade baml_language / the runtime engine if the failing serialization is a known bug

Example fix

// before
return_type.clone(),
// after
// ensure declared return type matches the actual value schema
// e.g. change fn return type or the value so baml.json receives a compatible class
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling write_output_with_context, confirm the value matches the declared return type schema
if !matches_return_type(value, expected_return_type) {
    return Err("value does not match declared return type; baml.json.serialize would fail");
}

Type guard

fn is_serializable_string_result(v: &BexExternalValue) -> bool {
    matches!(v, BexExternalValue::String(_))
}

Try / catch

match serialize_via_baml_json(...).await {
    Ok(json) => use(json),
    Err(e) if e.to_string().contains("baml.json.serialize failed") => {
        log::error!("serialization failed: {e:#}"); // inspect wrapped {e:?} cause
        fallback_render(value)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling write_output_with_context with a return type that routes through serialize_via_baml_json when the `baml.json` builtin/function evaluation fails — e.g. the runtime value cannot be converted by baml.json, the baml.json function itself errors, or the runtime/engine call rejects the arguments (type + `true` flag) passed in.

Common situations: Serializing a BAML class value whose fields contain types baml.json cannot handle; runtime engine errors during function invocation; mismatches between the return_type passed to baml.json and the actual value produced by the LLM function; partial or malformed results from an LLM response that fails conversion.

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 BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/87280b1df03b1122. Report an issue: GitHub.