{"record":{"id":"9365856a86af751e","repo":"zed-industries/zed","slug":"status-error-response-text-936585","errorCode":null,"errorMessage":"status error {}, response: {text:?}","messagePattern":"status error (.+?), response: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git_hosting_providers/src/providers/forgejo.rs","lineNumber":144,"sourceCode":"        // TODO: not renamed yet for compatibility reasons, may require a refactor later\n        // see https://github.com/zed-industries/zed/issues/11043#issuecomment-3480446231\n        if host == \"codeberg.org\"\n            && let Ok(codeberg_token) = std::env::var(\"CODEBERG_TOKEN\")\n        {\n            request = request.header(\"Authorization\", format!(\"Bearer {}\", codeberg_token));\n        }\n\n        let mut response = client\n            .send(request.body(AsyncBody::default())?)\n            .await\n            .with_context(|| format!(\"error fetching Forgejo commit details at {:?}\", url))?;\n\n        let mut body = Vec::new();\n        response.body_mut().read_to_end(&mut body).await?;\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 body_str = std::str::from_utf8(&body)?;\n\n        serde_json::from_str::<CommitDetails>(body_str)\n            .map(|commit| commit.author)\n            .context(\"failed to deserialize Forgejo commit details\")\n    }\n}\n\n#[async_trait]\nimpl GitHostingProvider for Forgejo {\n    fn name(&self) -> String {\n        self.name.clone()\n    }","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/git_hosting_providers/src/providers/forgejo.rs#L126-L162","documentation":"After fetching Forgejo commit details from /api/v1/repos/{owner}/{repo}/git/commits/{sha}, any HTTP 4xx status bails with the numeric code plus the raw response body text. It means the Forgejo instance itself rejected the request: 404 for an unknown repo/owner/commit, 401/403 for missing or under-scoped tokens, 429 for rate limiting. Only is_client_error() takes this path; server 5xx errors instead surface later as a deserialization failure.","triggerScenarios":"Calling the commit-author lookup with a wrong owner/repo pair, a commit sha that does not exist on that Forgejo instance (not pushed, or a sha from a fork), a missing/expired access token on a private repo (401/403), or polling fast enough to hit rate limits (429).","commonSituations":"Typo'd repository identifiers in a permalink; a commit not yet pushed or fetched so the server does not know the sha; a CI job using a token without read scope for the repo; aggressive polling of commit metadata.","solutions":["Verify the triple exists: open {base}/api/v1/repos/{owner}/{repo}/git/commits/{sha} in a browser or with curl using the same token","If 401/403, check the token is set, valid, and has read access to that repository","Treat 404 as Ok(None) when the author is only optional enrichment, instead of propagating an error","For 429, back off and retry honoring Retry-After"],"exampleFix":"// before\nif response.status().is_client_error() {\n    bail!(\"status error {}, response: {text:?}\", response.status().as_u16());\n}\n\n// after: 404 means 'unknown commit', not a hard failure\nlet status = response.status();\nif status.as_u16() == 404 {\n    return Ok(None);\n}\nif status.is_client_error() {\n    bail!(\"status error {}, response: {text:?}\", status.as_u16());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match provider.commit_author(owner, repo, sha).await {\n    Ok(author) => { /* render author */ }\n    Err(err) if err.to_string().contains(\"status error 404\") => {\n        // unknown repo/commit: treat as absent rather than an error\n    }\n    Err(err) if err.to_string().contains(\"status error 429\") => {\n        // back off and retry honoring Retry-After\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Derive owner/repo/commit from parsed VCS remotes and refs, not hand-typed strings","Cache 404 results so unknown commits are not re-fetched","Keep tokens valid and scoped; refresh before expiry","Never treat a 4xx body as parseable JSON — log it verbatim for diagnosis"],"tags":["forgejo","http-4xx","api-client","git-hosting","rate-limit"],"backgroundTag":"http-4xx-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"}