{"record":{"id":"b05204e7e76bd3cf","repo":"zed-industries/zed","slug":"failed-to-connect-to-api-b05204","errorCode":null,"errorMessage":"Failed to connect to API: {} {}","messagePattern":"Failed to connect to API: (.+?) (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/copilot_chat/src/responses.rs","lineNumber":319,"sourceCode":"    let request_builder = copilot_request_headers(\n        HttpRequest::builder().method(Method::POST).uri(&api_url),\n        &oauth_token,\n        Some(is_user_initiated),\n        Some(location),\n    )\n    .when(is_vision_request, |builder| {\n        builder.header(\"Copilot-Vision-Request\", \"true\")\n    });\n\n    let is_streaming = request.stream;\n    let json = serde_json::to_string(&request)?;\n    let request = request_builder.body(AsyncBody::from(json))?;\n    let mut response = client.send(request).await?;\n\n    if !response.status().is_success() {\n        let mut body = String::new();\n        response.body_mut().read_to_string(&mut body).await?;\n        anyhow::bail!(\"Failed to connect to API: {} {}\", response.status(), body);\n    }\n\n    if is_streaming {\n        let reader = BufReader::new(response.into_body());\n        Ok(reader\n            .lines()\n            .filter_map(|line| async move {\n                match line {\n                    Ok(line) => {\n                        let line = line.strip_prefix(\"data: \")?;\n                        if line.starts_with(\"[DONE]\") || line.is_empty() {\n                            return None;\n                        }\n\n                        match serde_json::from_str::<StreamEvent>(line) {\n                            Ok(event) => Some(Ok(event)),\n                            Err(error) => {\n                                log::error!(","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/copilot_chat/src/responses.rs#L301-L337","documentation":"Non-2xx guard in the Copilot 'responses' API client (responses.rs): the POST carrying the Responses-style request (with Copilot-Vision-Request header for image input) failed at the HTTP layer, and the bail embeds status plus full body text. Everything before the check succeeded - serialization, headers, body send - so the failure is server-side policy/auth/capacity, not request construction.","triggerScenarios":"Calling the Copilot responses endpoint with an expired OAuth token (401), non-entitled account or disabled model (403), rate limit (429), oversized conversation payload (413), or a vision request sent without vision entitlement (Copilot-Vision-Request: true on a non-vision account).","commonSituations":"Long agent conversations growing past request-size limits; model deprecation server-side; token expiry mid-session; enterprise Copilot policies disabling specific models.","solutions":["Parse the status/body from the message; 401 -> re-sign in to Copilot","Trim conversation history / reduce payload size for 413 responses","Switch model for 4xx model-policy rejections; verify entitlements","Retry with backoff on 429/5xx"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Keep payloads bounded to avoid 413 before sending\nif json.len() > MAX_REQUEST_BYTES {\n    request.messages.truncate_to_budget(MAX_REQUEST_BYTES);\n}","typeGuard":null,"tryCatchPattern":"match send_responses_request(/* .. */).await {\n    Ok(resp) => { /* handle */ }\n    Err(err) => {\n        let msg = format!(\"{err:#}\");\n        if msg.contains(\"401\") { /* re-auth */ }\n        else if msg.contains(\"413\") { /* trim history and retry */ }\n        else if msg.contains(\"429\") || msg.contains(\"50\") { /* backoff retry */ }\n        else { return Err(err); }\n    }\n}","preventionTips":["Trim/summarize long conversation histories client-side before hitting size limits","Cache the models list and only request entitled model ids","Distinguish retryable (429/5xx) from terminal (401/403) statuses in the handler"],"tags":["copilot","responses-api","http","authentication","rate-limit","rust"],"backgroundTag":"http-error-response","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}