BoundaryML/baml · error

{} {} Request options: {}

Error message

{} {}

Request options: {}

What it means

For LLMResponse::LLMFailure(e), run_test_with_expr_events formats an error as '{code} {message}\n\nRequest options: {json}' where the request options are first passed through scrub_baml_options to redact secrets (api keys, headers) using the provided env vars. This surfaces the provider's HTTP error code and message plus a sanitized dump of the request options that caused it.

Source

Thrown at engine/baml-runtime/src/lib.rs:1072

                    None,
                    env_vars.clone(),
                )
                .await;
            let res = response_res?;
            let (_, llm_resp, val) = res
                .event_chain()
                .iter()
                .last()
                .context("Expected non-empty event chain")?;
            if let Some(expr_tx) = expr_tx {
                expr_tx.unbounded_send(vec![]).unwrap();
            }
            let complete_resp = match llm_resp {
                LLMResponse::Success(complete_llm_response) => Ok(complete_llm_response),
                LLMResponse::InternalFailure(e) => Err(anyhow::anyhow!("{}", e)),
                LLMResponse::UserFailure(e) => Err(anyhow::anyhow!("{}", e)),
                LLMResponse::Cancelled(e) => Err(anyhow::anyhow!("Cancelled: {}", e)),
                LLMResponse::LLMFailure(e) => Err(anyhow::anyhow!({
                    let scrubbed_opts =
                        crate::redaction::scrub_baml_options(&e.request_options, &env_vars, false);
                    format!(
                        "{} {}\n\nRequest options: {}",
                        e.code,
                        e.message,
                        serde_json::to_string(&scrubbed_opts).unwrap_or_default()
                    )
                })),
            }?;
            let test_constraints_result = if constraints.is_empty() {
                TestConstraintsResult::empty()
            } else {
                match val {
                    Some(Ok(value)) => {
                        let value_with_constraints = value.0.map_meta(|m| m.1.clone());
                        evaluate_test_constraints(
                            &params,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the code and message: fix auth (401/403), model name (404), rate limits (429, add backoff), or request shape accordingly
  2. Inspect the redacted 'Request options' section to see exactly what was sent
  3. Verify env vars for keys/headers are set so the request is built correctly
  4. Check provider status pages if code is 5xx and retry later

Example fix

// before
{"model": "gpt-99-nonexistent", ...} // 404 LLMFailure
// after
{"model": "gpt-4o", ...}
Defensive patterns

Strategy: try-catch

Try / catch

// Parse the 'code message' prefix to branch on HTTP status
let err = match run_test_with_expr_events(...).await {
    Err(e) => e,
    Ok(r) => return Ok(r),
};
if let Some(code) = parse_http_code(&err.to_string()) {
    match code {
        429 => schedule_backoff_and_retry(),
        401 | 403 => eprintln!("fix credentials"),
        _ => eprintln!("provider error {code}: {err}"),
    }
}

Prevention

When it happens

Trigger: Running an expr-function test when the provider returns an HTTP error response that BAML maps to LLMResponse::LLMFailure; the formatted code/message/request options are raised as an anyhow error.

Common situations: 401/403 from bad API keys; 404 from a wrong model name; 429 rate limiting; 5xx provider outages; invalid request body rejected by the provider.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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