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

  1. Inspect the wrapped JsonishError message for the exact syntax problem
  2. Adjust the prompt to request strict, valid JSON
  3. Update/extend the jsonish repair heuristics if the format is legitimately supported
  4. 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

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


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