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
- Read the 'Detailed message:' section — it usually contains the provider's own diagnostic (rate limit, content filter, cancellation reason).
- For TimeoutError: increase timeout settings in the client options or reduce prompt/output size.
- For AbortError: check whether the request was cancelled (client disconnect, max retries) and adjust retry/finish reasons handling.
- 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
- Set generous but bounded timeouts in client options for long LLM calls.
- Inspect the Detailed message section for provider-specific causes before retrying.
- Distinguish Timeout from Abort errors to decide retry vs fail-fast.
- Log the full anyhow chain so finish reasons and provider diagnostics are preserved.
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
- AbortError: {detailed_message}
- Failed before LLM call: {message}
- Operation cancelled: {message}
- {e}
- LLM client "{client_name}" timed out: {message}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/f5fe5d9482fed719.
Report an issue: GitHub.