{"record":{"id":"2258d96115e5df78","repo":"zed-industries/zed","slug":"status-error-response-text-2258d9","errorCode":null,"errorMessage":"status error {}, response: {text:?}","messagePattern":"status error (.+?), response: (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/http_client/src/github.rs","lineNumber":59,"sourceCode":"    let url = format!(\"{GITHUB_API_URL}/repos/{repo_name_with_owner}/releases\");\n\n    let request = github_api_request(&url)?;\n\n    let mut response = http\n        .send(request)\n        .await\n        .context(\"error fetching latest release\")?;\n\n    let mut body = Vec::new();\n    response\n        .body_mut()\n        .read_to_end(&mut body)\n        .await\n        .context(\"error reading latest release\")?;\n\n    if response.status().is_client_error() {\n        let text = String::from_utf8_lossy(body.as_slice());\n        bail!(\n            \"status error {}, response: {text:?}\",\n            response.status().as_u16()\n        );\n    }\n\n    let releases = match serde_json::from_slice::<Vec<GithubRelease>>(body.as_slice()) {\n        Ok(releases) => releases,\n\n        Err(err) => {\n            log::error!(\"Error deserializing: {err:?}\");\n            log::error!(\n                \"GitHub API response text: {:?}\",\n                String::from_utf8_lossy(body.as_slice())\n            );\n            anyhow::bail!(\"error deserializing latest release: {err:?}\");\n        }\n    };\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/http_client/src/github.rs#L41-L77","documentation":"The GitHub release lister (latest_github_release) reads the full response body for GET /repos/{repo}/releases and bails on any 4xx status, embedding the numeric code and response text. 401 means bad credentials, 403 almost always means unauthenticated rate limit (60 req/h per IP) or a blocked token, and 404 means the owner/repo or the releases endpoint is wrong/private.","triggerScenarios":"Calling latest_github_release with a repo name that does not exist (typo, renamed repo, private without auth), without a GITHUB_TOKEN on a machine sharing a NATed IP that exhausted the 60 req/h anonymous limit, or with an expired/insufficient-scope token.","commonSituations":"Dev machines behind corporate NAT hitting the shared rate limit; CI jobs fetching extension/LSP binaries repeatedly; repos renamed or transferred so the old URL 404s; tokens revoked by GitHub.","solutions":["Check the embedded status: 403 → wait for the rate-limit reset or set a valid GITHUB_TOKEN; 404 → verify owner/repo spelling and visibility; 401 → refresh the token","Query GET /rate_limit to see remaining/reset before retrying","Cache the latest-release result instead of calling the API on every startup","Read the response text in the error message — GitHub states the exact reason (rate limit reset time, bad credentials)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight the shared anonymous rate limit before hammering /releases\nlet rl: serde_json::Value = serde_json::from_slice(\n    &http.get(\"https://api.github.com/rate_limit\", Default::default(), true).await?.body_mut().bytes().await?,\n)?;\nif rl[\"resources\"][\"core\"][\"remaining\"].as_i64() == Some(0) {\n    anyhow::bail!(\"rate limit exhausted, resets at epoch {}\", rl[\"resources\"][\"core\"][\"reset\"]);\n}","typeGuard":null,"tryCatchPattern":"match latest_github_release(...).await {\n    Ok(r) => Ok(r),\n    Err(e) if e.to_string().contains(\"status error 403\") => retry_after_reset().await,\n    Err(e) if e.to_string().contains(\"status error 404\") => Err(anyhow!(\"repo/release does not exist\")),\n    Err(e) => Err(e),\n}","preventionTips":["Always attach a token to GitHub API requests (60/h anonymous vs 5000/h authenticated)","Cache release metadata so startup does not re-fetch every run","Parse the numeric status out of the message and branch: 401 token, 403 rate limit, 404 wrong repo"],"tags":["github","http","api","rate-limit","release-download"],"backgroundTag":"github-api-client-error","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"}