BoundaryML/baml · error
request returned {status}: {resp_body}
Error message
request returned {status}:
{resp_body} What it means
The CLI API client wraps each HTTP response in into_result: success statuses are deserialized as JSON, while any non-success status reads the body as text and returns it verbatim in an anyhow error prefixed with the status. It exists so backend error payloads (HTML or JSON error bodies) reach the CLI user directly.
Source
Thrown at engine/cli/src/api_client.rs:41
// pub struct GetOrCreateProjectResponse {
// pub single_project: Option<Project>,
// #[allow(dead_code)]
// pub first_n_projects: Vec<Project>,
// pub total_project_count: u64,
// }
trait ApiResponse {
async fn into_result(self) -> Result<serde_json::Value>;
}
impl ApiResponse for reqwest::Response {
async fn into_result(self) -> Result<serde_json::Value> {
let status = self.status();
if status.is_success() {
Ok(self.json().await?)
} else {
let resp_body = self.text().await?;
Err(anyhow::anyhow!("request returned {status}:\n{resp_body}"))
}
}
}
#[derive(Debug, Serialize)]
pub struct CreateProjectRequest {
/// Example: "@boundaryml/baml"
pub project_fqn: String,
}
#[derive(Debug, Deserialize)]
pub struct CreateProjectResponse {
pub project: Project,
}
impl ApiClient {
pub async fn create_project(&self, req: CreateProjectRequest) -> Result<CreateProjectResponse> {
let resp = baml_runtime::request::create_client()?View on GitHub (pinned to bd85ce9dee)
Solutions
- Read the {status} and {resp_body} in the error: the body usually contains the server's specific error message
- For 401, refresh or re-authenticate (re-login / fix API key)
- For 404, verify the project/resource identifier used in the request
- For 5xx, retry after a delay; check service status if persistent
- For 429, apply backoff before retrying
Example fix
// before
let project = client.get(url).send().await?.into_result().await?;
// after
match client.get(url).send().await?.into_result().await {
Ok(project) => Ok(project),
Err(e) if e.to_string().contains("401") => {
client.reauthenticate().await?;
client.get(url).send().await?.into_result().await
}
Err(e) => Err(e),
} Defensive patterns
Strategy: try-catch
Validate before calling
if !api_token_is_set() { return Err(anyhow!("missing API token; run `baml-cli login` first")); } Try / catch
match resp.into_result().await {
Ok(v) => v,
Err(e) if e.to_string().starts_with("request returned 401") => reauth_and_retry().await,
Err(e) => return Err(e),
} Prevention
- Check the status code and body in the error message before assuming a client bug
- Refresh auth credentials when seeing 401 statuses
- Add retry/backoff for 429/5xx responses
- Validate resource identifiers client-side to avoid 404s
When it happens
Trigger: Any API call whose response status is not 2xx — 401 unauthorized, 404 project not found, 422 validation error, 5xx server error — causes into_result to bail with the status line and raw body.
Common situations: Expired/missing auth token (401); requesting a project or resource name that doesn't exist (404); server-side bugs or maintenance windows (500/502/503); rate limiting (429).
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
- Auth server returned {status}: {body}
- LLM client "{client_name}" failed with status code: {status_
- HTTP error: {status} {body}
- BamlError: BamlClientError: BamlClientHttpError: {message}
- usage: baml self-update unexpected arguments: {}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e2dee59f1115a411.
Report an issue: GitHub.