BoundaryML/baml · error · FetchError

HTTP {status} fetching {url}

Error message

HTTP {status} fetching {url}

What it means

FetchError::HttpStatus is thrown by baml_release when the release server responds with an HTTP error status code (anything non-successful that isn't a manifest 404, which has its own variant). The variant carries the URL and the reqwest::StatusCode so the developer can identify the failing endpoint and the specific status.

Source

Thrown at baml_language/crates/baml_release/src/lib.rs:80

pub enum Product {
    Toolchain,
    Wrapper,
}

impl Product {
    pub fn tag_prefix(self) -> &'static str {
        match self {
            Product::Toolchain => "baml-language",
            Product::Wrapper => "baml-wrapper",
        }
    }
}

#[derive(Debug, thiserror::Error)]
pub enum FetchError {
    #[error("network error fetching {url}: {source}")]
    Network { url: String, source: reqwest::Error },
    #[error("HTTP {status} fetching {url}")]
    HttpStatus {
        url: String,
        status: reqwest::StatusCode,
    },
    #[error("manifest 404 for version {version} (not released yet?)")]
    ManifestNotFound { version: String },
    #[error("manifest schema {got} not supported (max {max}); run `baml self-update`")]
    ManifestSchemaTooNew { got: u32, max: u32 },
    #[error("target {target} not built for version {version}")]
    TargetNotInManifest { target: String, version: String },
    #[error("sha256 mismatch for {url}: expected {expected}, got {got}")]
    ChecksumMismatch {
        url: String,
        expected: String,
        got: String,
    },
    #[error("archive missing expected binary {name}")]
    BinaryNotInArchive { name: String },

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Check the status code and URL in the error to identify the failing endpoint
  2. Retry if the status is 5xx — often transient during server deploys
  3. If 403/429, check proxy/WAF rules or rate limits between you and the release host
  4. Verify the release exists on the release server by fetching the URL manually
  5. Retry with an older/newer version argument if the endpoint for that version is broken

Example fix

// before (naive retry ignores status)
match fetch(url) { ... }
// after
match fetch(url) {
    Err(FetchError::HttpStatus { status, .. }) if status.is_server_error() =>
        retry_with_backoff(url),
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the endpoint before a full update flow
let status = reqwest::blocking::Client::new()
    .head(manifest_url).send().map(|r| r.status());

Type guard

fn is_http_status_err(e: &FetchError) -> Option<reqwest::StatusCode> {
    if let FetchError::HttpStatus { status, .. } = e { Some(*status) } else { None }
}

Try / catch

match fetch(url) {
    Err(FetchError::HttpStatus { status, .. }) if status.as_u16() == 429 =>
        wait_and_retry(rate_limit_delay),
    Err(FetchError::HttpStatus { status, .. }) if status.is_server_error() =>
        retry_with_backoff(2)?,
    Err(FetchError::HttpStatus { url, status }) =>
        bail!("release endpoint {url} returned {status}"),
    other => other,
}

Prevention

When it happens

Trigger: Any baml_release fetch/self-update API call that receives an error HTTP response (e.g. 500 from the release server, 403 from a CDN/WAF, 502/503 from a load balancer) instead of the expected manifest or archive bytes.

Common situations: Release CDN misconfiguration, a proxy/firewall intercepting the request and returning 403, the release server returning 5xx during deploys, or rate limiting returning 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


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