BoundaryML/baml · error · FetchError

HTTP fetching

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.

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.

Appendix: 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)