BoundaryML/baml · error
Depth limit reached. Likely a circular reference.
Error message
Depth limit reached. Likely a circular reference.
What it means
parse_func increments a depth counter on every recursive parse attempt and aborts when depth exceeds 100. This guards against pathological recursive input (e.g. deeply nested or self-referential structures) causing stack exhaustion; the message suggests the input looked like a circular reference.
Source
Thrown at engine/baml-lib/jsonish/src/jsonish/parser/entry.rs:20
use baml_types::CompletionState;
use super::ParseOptions;
use crate::jsonish::{
parser::{
fixing_parser,
markdown_parser::{self, MarkdownResult},
multi_json_parser,
},
value::Fixes,
Value,
};
pub(super) fn parse_func(str: &str, mut options: ParseOptions, is_done: bool) -> Result<Value> {
log::debug!("Parsing:\n{options:?}\n-------\n{str}\n-------");
options.depth += 1;
if options.depth > 100 {
return Err(anyhow::anyhow!(
"Depth limit reached. Likely a circular reference."
));
}
match serde_json::from_str(str) {
Ok(mut v) => {
match &mut v {
Value::String(_, completion_state) => {
// The string must have been contained in quotes in order
// to parse as a JSON string, therefore it is complete.
*completion_state = CompletionState::Complete;
}
Value::Number(_, completion_state) => {
*completion_state = CompletionState::Incomplete;
}
Value::Boolean(_) => {}
Value::Object(_, _) => {}
Value::Array(_, _) => {}View on GitHub (pinned to bd85ce9dee)
Solutions
- Inspect the raw input for runaway nested brackets or repeated prefixes and truncate/clean it before parsing
- Retry the LLM generation with instructions to emit flat, valid JSON
- If legitimately deep input is expected, raise the depth limit in ParseOptions/entry.rs
- Catch the error and fall back to a lenient extractor (e.g. markdown parser or regex extraction)
Defensive patterns
Strategy: validation
Validate before calling
fn nesting_depth(s: &str) -> usize {
let mut d = 0usize; let mut max = 0usize;
for c in s.chars() { match c { '{' | '[' => { d += 1; max = max.max(d); } '}' | ']' => d = d.saturating_sub(1), _ => {} } }
max
}
// reject if nesting_depth(input) > 60 Try / catch
match parse(input) {
Err(e) if e.to_string().contains("Depth limit") => retry_flat_generation(),
other => other,
} Prevention
- Scan for runaway bracket repetition before parsing
- Cap max output tokens to reduce loop degeneration
- Instruct the model to emit flat JSON
When it happens
Trigger: Calling jsonish parse/parse_func (directly or via from_str) with input whose repair attempts recurse more than 100 levels — extremely deeply nested arrays/objects or a fixer that repeatedly re-wraps content.
Common situations: LLM output containing hundreds of nested brackets (e.g. model loops generating '[[' repetition), or parser repair heuristics feeding their own output back in.
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
- Depth limit reached. Likely a circular reference.
- No JSON objects found
- Mismatched brackets
- No collection to consume token: {0:?}
- Failed to parse JSON
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e400d8aa1981b079.
Report an issue: GitHub.