BoundaryML/baml · error · ExposedError

{self}\n\nDetailed message: {detailed_message}

Error message

{self}\n\nDetailed message: {detailed_message}

What it means

ExposedError::to_anyhow_with_details converts an ExposedError (Timeout, Abort, etc.) into an anyhow::Error, appending a more verbose detailed_message (present on some variants like AbortError) to the standard Display output. This is a formatting/conversion of an LLM call failure rather than a new failure itself.

Source

Thrown at engine/baml-runtime/src/errors.rs:63

    pub fn to_anyhow_with_details(&self) -> anyhow::Error {
        let detailed_message = match self {
            ExposedError::ValidationError {
                detailed_message, ..
            } => detailed_message,
            ExposedError::FinishReasonError {
                detailed_message, ..
            } => detailed_message,
            ExposedError::ClientHttpError {
                detailed_message, ..
            } => detailed_message,
            ExposedError::TimeoutError { message, .. } => message,
            ExposedError::AbortError {
                detailed_message, ..
            } => detailed_message,
        };
        let with_details = format!("{self}\n\nDetailed message: {detailed_message}");
        anyhow::anyhow!(with_details)
    }
}

impl std::error::Error for ExposedError {}

impl std::fmt::Display for ExposedError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ExposedError::ValidationError {
                prompt,
                raw_output,
                message,
                detailed_message: _,
            } => {
                write!(
                    f,
                    "Parsing error: {message}\nPrompt: {prompt}\nRaw Response: {raw_output}"
                )

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the 'Detailed message:' section — it usually contains the provider's own diagnostic (rate limit, content filter, cancellation reason).
  2. For TimeoutError: increase timeout settings in the client options or reduce prompt/output size.
  3. For AbortError: check whether the request was cancelled (client disconnect, max retries) and adjust retry/finish reasons handling.
  4. Inspect the underlying finish_reason/finish_reason_raw on the error struct for programmatic handling.

Example fix

// before
let result = client.chat(messages)?; // panics/aborts with terse message
// after
match client.chat(messages) {
    Ok(r) => r,
    Err(e) => {
        if e.to_string().contains("Detailed message") {
            eprintln!("LLM call failed: {e}"); // includes provider details
        }
        return Err(e);
    }
}
Defensive patterns

Strategy: try-catch

Type guard

fn is_timeout_or_abort(err: &anyhow::Error) -> bool {
    let s = err.to_string();
    s.contains("Timeout") || s.contains("Abort")
}

Try / catch

match client.chat(messages) {
    Ok(r) => r,
    Err(e) => {
        let msg = e.to_string();
        let detailed = msg.split("Detailed message:").nth(1).unwrap_or("").trim();
        if msg.contains("TimeoutError") {
            retry_with_backoff(3);
        } else if msg.contains("AbortError") {
            log::warn!("request aborted: {detailed}");
        }
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Any caller that invokes to_anyhow_with_details on an ExposedError — typically when surfacing a failed LLM request (timeout, abort, provider error) up through anyhow-based error chains in the runtime.

Common situations: A provider request times out or is aborted mid-stream and the runtime reports the full detailed message; users see the concise error plus 'Detailed message:' with provider-side diagnostics (rate limits, content filter, incomplete responses).

Related errors


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