BoundaryML/baml · error

No JSON objects found

Error message

No JSON objects found

What it means

The fixing (partial/streaming JSON) parser tracks completed values as it scans the input; when parsing finishes and zero values were completed, the public parse() returns 'No JSON objects found'. This happens for input that contains no salvageable object/array at all.

Source

Thrown at engine/baml-lib/jsonish/src/jsonish/parser/fixing_parser.rs:55

                for _ in 0..increments {
                    chars.next();
                }
            }
            Err(e) => {
                return Err(e);
            }
        }
    }

    // If we still have a collection open, close it
    while !state.collection_stack.is_empty() {
        state.complete_collection(CompletionState::Incomplete);
    }

    // Determine what to return.

    match state.completed_values.len() {
        0 => Err(anyhow::anyhow!("No JSON objects found")),
        1 => state
            .completed_values
            .pop()
            .map(|(_name, value, fixes)| Ok(vec![(value, fixes)]))
            .unwrap_or(Err(anyhow::anyhow!("Failed to pop completed value"))),
        _ => {
            if state.completed_values.iter().all(|f| f.0 == "string") {
                // If all the values are strings, return them as an array of strings
                Ok(vec![(
                    Value::Array(
                        state
                            .completed_values
                            .into_iter()
                            .map(|f| {
                                let completion_state = f.1.completion_state().clone();
                                Value::FixedJson(f.1.into(), f.2)
                            })
                            .collect(),

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Check the input for any '{' or '[' before invoking the fixing parser
  2. Wait for a chunk that actually contains JSON start content before parsing partials
  3. Wrap in try/catch and keep the previous successful partial value
  4. Pre-filter the response (e.g. strip prose, extract fenced blocks) before parsing

Example fix

// before
let vals = fixing_parser::parse(input)?;
// after
if input.trim_start().starts_with(['{', '[']) {
    let vals = fixing_parser::parse(input)?;
}
Defensive patterns

Strategy: validation

Validate before calling

fn worth_fixing(s: &str) -> bool { s.contains('{') || s.contains('[') }

Try / catch

match fixing_parser::parse(chunk) {
    Err(e) if e.to_string().contains("No JSON objects") => Ok(last_good_value.clone()),
    other => other,
}

Prevention

When it happens

Trigger: Calling fixing_parser::parse with an empty string, plain prose, or input where no object/array was ever opened/completed (0 completed_values).

Common situations: Streaming chunks that so far contain only whitespace or explanatory text before the JSON begins; empty LLM completions.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/27fa3b12a39f3e43. Report an issue: GitHub.