{"record":{"id":"491652ae2f262ee3","repo":"zed-industries/zed","slug":"baseten-api-returned-status-body","errorCode":null,"errorMessage":"Baseten API returned {status}: {body}","messagePattern":"Baseten API returned (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/edit_prediction_cli/src/predict.rs","lineNumber":675,"sourceCode":"    let request = http_client::Request::builder()\n        .method(Method::POST)\n        .uri(&url)\n        .header(\"Content-Type\", \"application/json\")\n        .header(\"Authorization\", format!(\"Api-Key {api_key}\"))\n        .body(AsyncBody::from(body_bytes))?;\n\n    let mut response = http_client.send(request).await?;\n    let status = response.status();\n\n    let mut body = String::new();\n    response\n        .body_mut()\n        .read_to_string(&mut body)\n        .await\n        .context(\"Failed to read Baseten response body\")?;\n\n    if !status.is_success() {\n        anyhow::bail!(\"Baseten API returned {status}: {body}\");\n    }\n\n    let completion: RawCompletionResponse =\n        serde_json::from_str(&body).context(\"Failed to parse Baseten response\")?;\n\n    let actual_output = completion\n        .choices\n        .into_iter()\n        .next()\n        .map(|choice| choice.text)\n        .unwrap_or_default();\n\n    let actual_output = format!(\"{prefill}{actual_output}\");\n\n    let (actual_patch, actual_cursor) =\n        parse_prediction_output(example, &actual_output, PredictionProvider::Zeta2(format))?;\n\n    let prediction = ExamplePrediction {","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/edit_prediction_cli/src/predict.rs#L657-L693","documentation":"Raised in predict.rs when the HTTP call to the Baseten model-serving API completes with a non-2xx status. The message embeds both the status code and the raw response body, which usually contains Baseten's error detail (auth failure, cold-start/gateway error, invalid model id, or an application-level exception raised inside the deployed model). Parsing of the body as RawCompletionResponse happens only after this check, so a bail here means the gateway answered with an error page, not a completion.","triggerScenarios":"Using the baseten provider for prediction: expired/invalid BASSETEN_API_KEY -> 401/403; wrong model deployment id -> 404; model crashed or timed out inside the deployment -> 500 with a traceback in {body}; rate limiting -> 429.","commonSituations":"Rotated API keys not updated in the environment; deployment id from a different Baseten project or a redeployed model; intermittent 502/504 while the deployment cold-starts under load.","solutions":["Read the embedded status and body: 401/403 -> fix the API key, 404 -> fix the model/deployment id, 429 -> back off, 5xx -> retry shortly","Verify the deployment is live and healthy in the Baseten dashboard before re-running","For transient 5xx/429 wrap the run in a retry with backoff; predictions are per-example so a re-run resumes from existing results"],"exampleFix":"// before: single shot, whole run dies on one 502\nlet response = client.send(request).await?;\n\n// after: retry transient statuses\nfor attempt in 0..3 {\n    let response = client.send(request.clone()).await?;\n    if response.status().is_success() || response.status().as_u16() < 500 { break; }\n    tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in 0..4 {\n    match send_baseten_request(&client, &request).await {\n        Ok(resp) => return Ok(resp),\n        Err(e) if attempt < 3 && e.to_string().contains(\"Baseten API returned 5\") => {\n            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt as u32))).await;\n        }\n        Err(e) if e.to_string().contains(\"Baseten API returned 40\") => {\n            anyhow::bail!(\"Baseten auth/model id problem, do not retry: {e:#}\");\n        }\n        Err(e) => return Err(e),\n    }\n}\nunreachable!()","preventionTips":["Keep the Baseten API key and deployment id in env/config checked before long runs, and verify with one tiny request first","Retry only transient statuses (429/5xx); 401/403/404 indicate config errors that retrying cannot fix","Read the embedded body — Baseten usually returns the model-side traceback for 500s"],"tags":["rust","baseten","http","api-error","edit-prediction"],"backgroundTag":"api-error-response","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}