BoundaryML/baml · warning · ExposedError::AbortError
AbortError: {detailed_message}
Error message
AbortError: {detailed_message} What it means
BAML aborts an in-flight LLM stream when the caller cancels the operation (e.g. request dropped, deadline hit, or a client-side cancel token fires). The orchestrator's select loop breaks on the cancel future and records a Cancelled LLMResponse carrying an AbortError. It signals the work was stopped by the caller, not that the model or network failed.
Source
Thrown at engine/baml-runtime/src/internal/llm_client/orchestrator/stream.rs:200
as std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>>,
None => Box::pin(futures::future::pending()),
};
tokio::pin!(cancel_future);
//advanced curl viewing, use render_raw_curl on each node. TODO
let total_nodes = iter.len();
for (node_index, node) in iter.into_iter().enumerate() {
let is_last_node = node_index == total_nodes - 1;
// Check for cancellation at the start of each iteration
let cancel_scope = node.scope.clone();
tokio::select! {
biased;
_ = &mut cancel_future => {
results.push((
cancel_scope,
LLMResponse::Cancelled("Operation cancelled".to_string()),
Some(Err(anyhow::anyhow!(
crate::errors::ExposedError::AbortError {
detailed_message: String::new()
}
))),
));
break;
}
result = async {
let prompt = match node.render_prompt(ir, prompt, ctx, params).await {
Ok(p) => p,
Err(e) => {
return Some((
node.scope,
LLMResponse::InternalFailure(e.to_string()),
Some(Err(anyhow::anyhow!(e.to_string()))),
));
}
};View on GitHub (pinned to bd85ce9dee)
Solutions
- Check upstream cancellation handling first — this is usually expected behavior, not a bug
- Increase server/gateway timeouts (e.g. proxy read timeout) if long generations are killed prematurely
- Ensure the client does not abort the fetch/request before consuming the full stream
- Handle the Cancelled/AbortError case explicitly in your on_event/error callback instead of treating it as a model failure
Example fix
// before
const res = await b.functions.Extract(text); // client times out at 10s
// after
const res = await b.functions.Extract(text, { tbConfig: { timeoutMs: 120000 } }); // align timeout with expected generation time Defensive patterns
Strategy: try-catch
Validate before calling
// Node: abort only when truly needed const controller = new AbortController(); setTimeout(() => controller.abort(), 120000); // generous timeout > generation time
Try / catch
try {
const res = await b.functions.Extract(input);
} catch (e) {
if (e instanceof BamlAbortError || /AbortError|cancelled/i.test(String(e))) {
return; // expected cancellation, not a model failure
}
throw e;
} Prevention
- Set timeouts longer than worst-case LLM generation
- Don't abort requests on UI unmount unless the result is discarded intentionally
- Log cancellations separately from real errors
- Keep gateway/proxy read timeouts aligned with generation length
When it happens
Trigger: Calling a BAML function via orchestrate_stream (through run) and cancelling the future/request before the stream completes — HTTP client disconnects, tokio timeout, user aborts UI request, or explicit cancellation token triggered mid-stream.
Common situations: Web server clients closing the browser tab mid-generation; server frameworks dropping the request context; fetch/axios AbortController firing; gateway timeouts shorter than LLM generation time.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- Operation was aborted
- AbortError: {detailed_message}
- ExposedError::AbortError { detailed_message }
- BamlAbortError: Operation was aborted: {msg}
- -32800
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/84e4553fc74e51bf.
Report an issue: GitHub.