BoundaryML/baml · error
Failed before LLM call (user error)
Error message
Failed before LLM call (user error): {message} What it means
LLMResponse::content() also distinguishes failures that happened before any LLM call was made due to a user error; the UserFailure variant carries a message (typically from a BAML assert/raise, or argument/pre-call validation performed by user logic), and content() surfaces it verbatim as 'Failed before LLM call (user error)'. It separates user-induced pre-call failures from LLM/network failures.
Solutions
- Read the embedded message — it states the user-level reason the call was aborted
- Fix the inputs or the failing assert/raise condition in the BAML function before retrying
- Handle the UserFailure variant explicitly instead of relying on content()
- Review prompt/input validation logic that raises user failures
Example fix
// before
let text = response.content()?; // panics into generic user-error message
// after
if let LLMResponse::UserFailure(msg) = &response {
eprintln!("pre-call user failure: {msg}"); // fix input/assert, then retry
return Err(UserFacingError(msg.clone()));
}
let text = response.content()?; Defensive patterns
Strategy: type-guard
Type guard
fn is_user_failure(r: &LLMResponse) -> Option<&str> {
match r { LLMResponse::UserFailure(m) => Some(m), _ => None }
} Try / catch
match llm_response {
LLMResponse::UserFailure(msg) => Err(UserError(msg.clone())), // fix inputs/asserts, no retry
other => other.content().map(|s| s.to_string()),
} Prevention
- Check BAML assert/raise conditions against your inputs before invoking
- Handle UserFailure distinctly from LLMFailure — it is not retryable
- Validate prompt parameters and function arguments before the call
- Surface the embedded user message to end users rather than a generic error
When it happens
Trigger: Calling .content() on an LLMResponse::UserFailure — produced when user-level checks (e.g. BAML raise/assert semantics or explicit user failure injection) short-circuit before the provider request is sent.
Common situations: BAML functions with assert/raise clauses whose conditions failed on the inputs; application logic deliberately marking the call as failed before sending; misconfigured prompts/parameters caught by pre-call validation.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/24a2d27391682a32.
Report an issue: GitHub.
Appendix: source
Thrown at engine/baml-runtime/src/internal/llm_client/mod.rs:201
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Success(response) => write!(f, "{response}"),
Self::LLMFailure(failure) => write!(f, "LLM call failed: {failure:?}"),
Self::UserFailure(message) => {
write!(f, "Failed before LLM call (user error): {message}")
}
Self::InternalFailure(message) => write!(f, "Failed before LLM call: {message}"),
Self::Cancelled(message) => write!(f, "Operation cancelled: {message}"),
}
}
}
impl LLMResponse {
pub fn content(&self) -> Result<&str> {
match self {
Self::Success(response) => Ok(&response.content),
Self::LLMFailure(failure) => Err(anyhow::anyhow!("LLM call failed: {failure:?}")),
Self::UserFailure(message) => Err(anyhow::anyhow!(
"Failed before LLM call (user error): {message}"
)),
Self::InternalFailure(message) => {
Err(anyhow::anyhow!("Failed before LLM call: {message}"))
}
Self::Cancelled(message) => Err(anyhow::anyhow!("Operation cancelled: {message}")),
}
}
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct LLMErrorResponse {
pub client: String,
pub model: Option<String>,
pub prompt: RenderedPrompt,
pub request_options: BamlMap<String, serde_json::Value>,
#[cfg_attr(target_arch = "wasm32", serde(skip_serializing))]
pub start_time: web_time::SystemTime,View on GitHub (pinned to bd85ce9dee)