BoundaryML/baml · error
Failed before LLM call: {message}
Error message
Failed before LLM call: {message} What it means
BAML wraps LLM client outcomes in an LLMResponse enum. The InternalFailure variant is produced when something went wrong inside BAML before any LLM API request was attempted (e.g. prompt rendering failed). When you call .content() on such a response, this anyhow error is raised carrying the internal message. It is not a model/provider error — the request never left the runtime.
Source
Thrown at engine/baml-runtime/src/internal/llm_client/mod.rs:205
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,
pub latency: web_time::Duration,
// Short error message
pub message: String,View on GitHub (pinned to bd85ce9dee)
Solutions
- Read the embedded {message} to identify the pre-call failure (most often prompt rendering).
- Fix the underlying prompt/param problem: check variable names, Jinja syntax, and that all required params are supplied to the BAML function call.
- Check function failure with on_error / FunctionFailure instead of calling content() directly, so failure details reach your handler.
- Verify your BAML clients and prompts compile with `baml-cli dev` — IR errors here surface as InternalFailure.
Example fix
// before
let text = response.content()?; // panics into anyhow: Failed before LLM call: ...
// after
match response {
LLMResponse::Success(r) => Ok(r.content.clone()),
other => Err(anyhow::anyhow!("LLM unavailable: {other:?}")),
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate prompt inputs before calling the BAML function
fn validate_params(params: &serde_json::Map<String, serde_json::Value>, required: &[&str]) -> Result<(), String> {
required.iter().find(|k| !params.contains_key(**k))
.map(|k| format!("missing param: {k}"))
.map_or(Ok(()), Err)
} Type guard
fn has_content(resp: &LLMResponse) -> bool {
matches!(resp, LLMResponse::Success(_))
} Try / catch
match llm_response.content() {
Ok(c) => process(c),
Err(e) if e.to_string().starts_with("Failed before LLM call") => {
log::error!("pre-call failure: {e:#}");
fallback()
}
Err(e) => return Err(e),
} Prevention
- Run `baml-cli dev` in CI so prompt/IR errors are caught before runtime.
- Always check the response variant (FunctionSuccess vs FunctionFailure) before accessing content().
- Keep template variables in sync with function params; use typed BAML clients from codegen.
When it happens
Trigger: Calling LLMResponse::content() (via the public API or FunctionSuccess/FunctionFailure helpers) when the response is LLMResponse::InternalFailure, which the orchestrator produces when render_prompt fails for an orchestration node before single_call is made.
Common situations: Invalid template/Jinja expressions or missing params in the prompt; IR lookup failures after config edits; BAML internal invariant violations surfaced as stringified errors; passing a FunctionFailure result straight to content() without checking success.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- {e}
- args must be a map
- {self}\n\nDetailed message: {detailed_message}
- Operation cancelled: {message}
- AbortError: {detailed_message}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/1f8117bd2fa0fb63.
Report an issue: GitHub.