{"record":{"id":"7da942344736e645","repo":"astrid-runtime/astrid","slug":"models-endpoint-returned-http","errorCode":null,"errorMessage":"models endpoint returned HTTP {}","messagePattern":"models endpoint returned HTTP (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/capsule/model_discovery.rs","lineNumber":233,"sourceCode":"                \"withholding options-from bearer: fetch host does not match the \\\n                 configured provider ({PROVIDER_BASE_URL_KEY}) host\"\n            );\n            false\n        },\n    });\n\n    let client = reqwest::Client::builder()\n        .user_agent(\"astrid-cli\")\n        .timeout(std::time::Duration::from_secs(15))\n        .build()?;\n\n    let mut request = client.get(&url);\n    if let Some(token) = bearer {\n        request = request.bearer_auth(token);\n    }\n\n    let response = request.send().await?;\n    anyhow::ensure!(\n        response.status().is_success(),\n        \"models endpoint returned HTTP {}\",\n        response.status()\n    );\n\n    // Cap the body: the endpoint is operator-supplied and otherwise\n    // unbounded. Reject up-front on an advertised over-limit length so a\n    // hostile `Content-Length` can't even start a large transfer (fast\n    // path), then stream-read with the same bound so an absent/lying length\n    // (e.g. a chunked response with no `Content-Length`) cannot OOM the\n    // installer either. An over-limit response errors → free-text fallback.\n    anyhow::ensure!(\n        response\n            .content_length()\n            .is_none_or(|len| len <= MAX_RESPONSE_BYTES as u64),\n        \"models response too large (advertised {} bytes; limit {MAX_RESPONSE_BYTES})\",\n        response.content_length().unwrap_or_default()\n    );","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/capsule/model_discovery.rs#L215-L251","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the endpoint URL is the correct models path on a running server","Set/correct the bearer token in the capsule config for authenticated endpoints","Inspect the returned HTTP status (in the error text) and fix server-side cause (auth, routing, health)"],"exampleFix":"// before\nendpoint = \"https://host/api/models\"   // 404\n// after\nendpoint = \"https://host/v1/models\"   // 200","handlingStrategy":"try-catch","validationCode":"let resp = reqwest::get(&url).await?;\nif !resp.status().is_success() {\n    eprintln!(\"endpoint unreachable, status {}\", resp.status());\n    return Ok(()); // use free-text fallback\n}","typeGuard":null,"tryCatchPattern":"match fetch_options(opts, values).await {\n    Err(e) if e.to_string().contains(\"models endpoint returned HTTP\") => {\n        eprintln!(\"Discovery failed ({}); enter the model name manually.\", e);\n        prompt_free_text()?\n    }\n    other => other?,\n}","preventionTips":["Verify bearer tokens and endpoint paths against the server's API docs","Curl the models endpoint manually to confirm 200 responses before configuring","Monitor server health/auth expiry for endpoints used in capsules"],"tags":["http","network","api"],"backgroundTag":"http-error-response","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}