BoundaryML/baml · error · LlmOpError
Jsonish error: {0}
Error message
Jsonish error: {0} What it means
LlmOpError::JsonishError wraps a bex_sap::jsonish::JsonishError produced while flexibly parsing raw LLM output into a JSON-ish value. It surfaces the underlying jsonish parser's failure through the unified LlmOpError enum.
Source
Thrown at baml_language/crates/sys_ops/src/sap.rs:61
self.db().resolve_with_meta(self.types.stream_ty().as_ref())
}
}
/// Errors that can occur during LLM operations. Relocated verbatim from
/// `sys_llm`; only `ParseResponseError`, `JsonishError` and `SapError` are
/// still constructible now that the SAP parse entry points are the sole users.
#[derive(Debug, thiserror::Error)]
pub enum LlmOpError {
#[error("Expected {expected}, got {actual}")]
TypeError {
expected: &'static str,
actual: String,
},
#[error("Parse response error: {0}")]
ParseResponseError(String),
#[error("Jsonish error: {0}")]
JsonishError(::bex_sap::jsonish::JsonishError),
#[error("SAP error: {0}")]
SapError(::bex_sap::deserializer::coercer::ParsingError),
}
impl From<LlmOpError> for ::sys_types::VmRustFnError {
fn from(e: LlmOpError) -> Self {
let baml: ::sys_types::VmBamlError = match e {
LlmOpError::TypeError { expected, actual } => {
::sys_types::VmBamlError::InvalidArgument {
message: format!("expected {expected}, got {actual}"),
}
}
LlmOpError::ParseResponseError(e) => ::sys_types::VmBamlError::LlmClient { message: e },
LlmOpError::JsonishError(e) => ::sys_types::VmBamlError::LlmClient {
message: e.to_string(),
},View on GitHub (pinned to bd85ce9dee)
Solutions
- Inspect the wrapped JsonishError message for the exact syntax problem
- Adjust the prompt to request strict, valid JSON
- Update/extend the jsonish repair heuristics if the format is legitimately supported
- Retry the request, since LLM formatting faults are often transient
Example fix
// before
match jsonish::parse(text) { Err(e) => return Err(LlmOpError::JsonishError(e)), ... }
// after
let text = strip_markdown_fences(text);
match jsonish::parse(text) { ... } Defensive patterns
Strategy: retry
Validate before calling
if raw.trim().is_empty() { return Err("empty response before jsonish parse".into()); } Type guard
fn looks_like_json(s: &str) -> bool { let t = s.trim(); (t.starts_with('{') && t.ends_with('}')) || (t.starts_with('[') && t.ends_with(']')) } Try / catch
match result {
Err(LlmOpError::JsonishError(e)) => { log::warn!("jsonish: {e}"); strip_fences_and_retry(raw) }
other => other,
} Prevention
- Instruct the model to emit bare JSON without markdown fences
- Preprocess responses to strip fences/prose before parsing
- Retry generation when repair fails
When it happens
Trigger: The jsonish parser invoked from the SAP parse entry points cannot convert the model's raw text (bad JSON syntax, unrepairable partial JSON) into a value, and the error is wrapped as JsonishError.
Common situations: Model emits JSON with trailing commas, comments, or markdown fences the repairer can't handle; empty responses; encoding issues.
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/5c6624086ebbd44e.
Report an issue: GitHub.