astrid-runtime/astrid · error

models endpoint returned HTTP {}

Error message

models endpoint returned HTTP {}

What it means

fetch_options requires the models endpoint to return a successful HTTP status and otherwise throws with the status code. Operator-supplied endpoints may return 401/404/500 etc., and the error is surfaced so callers can fall back to free-text input.

Source

Thrown at crates/astrid-cli/src/commands/capsule/model_discovery.rs:233

                "withholding options-from bearer: fetch host does not match the \
                 configured provider ({PROVIDER_BASE_URL_KEY}) host"
            );
            false
        },
    });

    let client = reqwest::Client::builder()
        .user_agent("astrid-cli")
        .timeout(std::time::Duration::from_secs(15))
        .build()?;

    let mut request = client.get(&url);
    if let Some(token) = bearer {
        request = request.bearer_auth(token);
    }

    let response = request.send().await?;
    anyhow::ensure!(
        response.status().is_success(),
        "models endpoint returned HTTP {}",
        response.status()
    );

    // Cap the body: the endpoint is operator-supplied and otherwise
    // unbounded. Reject up-front on an advertised over-limit length so a
    // hostile `Content-Length` can't even start a large transfer (fast
    // path), then stream-read with the same bound so an absent/lying length
    // (e.g. a chunked response with no `Content-Length`) cannot OOM the
    // installer either. An over-limit response errors → free-text fallback.
    anyhow::ensure!(
        response
            .content_length()
            .is_none_or(|len| len <= MAX_RESPONSE_BYTES as u64),
        "models response too large (advertised {} bytes; limit {MAX_RESPONSE_BYTES})",
        response.content_length().unwrap_or_default()
    );

View on GitHub (pinned to affd8760f4)

Solutions

  1. Check the endpoint URL is the correct models path on a running server
  2. Set/correct the bearer token in the capsule config for authenticated endpoints
  3. Inspect the returned HTTP status (in the error text) and fix server-side cause (auth, routing, health)

Example fix

// before
endpoint = "https://host/api/models"   // 404
// after
endpoint = "https://host/v1/models"   // 200
Defensive patterns

Strategy: try-catch

Validate before calling

let resp = reqwest::get(&url).await?;
if !resp.status().is_success() {
    eprintln!("endpoint unreachable, status {}", resp.status());
    return Ok(()); // use free-text fallback
}

Try / catch

match fetch_options(opts, values).await {
    Err(e) if e.to_string().contains("models endpoint returned HTTP") => {
        eprintln!("Discovery failed ({}); enter the model name manually.", e);
        prompt_free_text()?
    }
    other => other?,
}

Prevention

When it happens

Trigger: The GET request to the resolved models URL returns a non-success status — wrong API path, missing/invalid bearer token (401), server error (5xx), or wrong port/host.

Common situations: Expired or missing API token against an OpenAI-compatible server; endpoint path typo (e.g. /v1/model vs /v1/models); server down or behind a proxy returning errors.

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 astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/7da942344736e645. Report an issue: GitHub.