{"record":{"id":"08decacf3f8034ed","repo":"GitoxideLabs/gitoxide","slug":"received-http-status","errorCode":null,"errorMessage":"Received HTTP status {}","messagePattern":"Received HTTP status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-transport/src/client/blocking_io/http/reqwest/remote.rs","lineNumber":197,"sourceCode":"                    Err(err) => {\n                        // `error_for_status()` preserves the final URL for HTTP error responses. Capture it here so\n                        // authentication retries after redirected 401 responses use the redirected base URL.\n                        if let Some(actual_url) = err.url().map(reqwest::Url::as_str)\n                            && actual_url != effective_url\n                        {\n                            let new_base_url = redirect::base_url(actual_url, &base_url, url.clone())?;\n                            *redirected_base_url_shared.lock() = Some(new_base_url);\n                        }\n                        let err = match err.status() {\n                            Some(status) => {\n                                let kind = if status == reqwest::StatusCode::UNAUTHORIZED {\n                                    std::io::ErrorKind::PermissionDenied\n                                } else if status.is_server_error() {\n                                    std::io::ErrorKind::ConnectionAborted\n                                } else {\n                                    std::io::ErrorKind::Other\n                                };\n                                std::io::Error::new(kind, format!(\"Received HTTP status {}\", status.as_str()))\n                            }\n                            // Preserve the `reqwest::Error` as the source so the underlying cause -- e.g. a\n                            // connection or TLS failure -- isn't lost. It was previously stringified, which\n                            // dead-ended `source()` and hid the real reason a request failed. See #2140.\n                            None => std::io::Error::other(err),\n                        };\n                        headers_tx.channel.send(Err(err)).ok();\n                        continue;\n                    }\n                };\n\n                let actual_url = res.url().as_str();\n                if actual_url != effective_url.as_str() {\n                    let new_base_url = redirect::base_url(actual_url, &base_url, url)?;\n                    *redirected_base_url_shared.lock() = Some(new_base_url);\n                }\n\n                let send_headers = {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-transport/src/client/blocking_io/http/reqwest/remote.rs#L179-L215","documentation":"The HTTP remote (reqwest-based) received a non-success HTTP status from the server and converts it into an `io::Error` whose message carries the status string, with an ErrorKind mapped by status class (PermissionDenied for 401/403-style auth failures, ConnectionAborted for 5xx, Other otherwise). This indicates the server rejected the request.","triggerScenarios":"Any git HTTP operation (fetch/clone/push over the reqwest transport) where the server responds with an error status — 401/403 auth failures, 404 repo not found, 5xx server errors, rate limiting (429).","commonSituations":"Wrong or expired credentials/tokens; private repository with insufficient access; GitHub/GitLab outages or rate limits; proxy interference returning error pages.","solutions":["Check the HTTP status in the message and fix auth: update tokens/credentials via the configured credential helper","Verify the repository URL exists and the account has access","Retry on 5xx/429 with backoff; check the provider's status page for outages"],"exampleFix":"// before (403)\nlet mut conn = gix::connect(url, gix::protocol::transport::Protocol::Http)?;\n// after: embed credentials\nlet url = format!(\"https://token@github.com/user/repo.git\");\nlet mut conn = gix::connect(url, gix::protocol::transport::Protocol::Http)?;","handlingStrategy":"retry","validationCode":"fn check_url(url: &str) -> Result<(), String> {\n    let u = gix::url::parse(url.into())?;\n    if u.scheme != gix::url::Scheme::Https { return Err(\"expected https\".into()); }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match remote.fetch(...) {\n    Err(e) if e.to_string().contains(\"Received HTTP status\") => {\n        if e.to_string().contains(\"403\") || e.to_string().contains(\"401\") {\n            // refresh credentials via credential helper, then retry once\n        } else {\n            // 5xx/429: retry with exponential backoff\n        }\n    }\n    other => other?,\n}","preventionTips":["Keep credentials/tokens fresh and scoped to the repo","Check provider status pages before assuming a code bug on 5xx","Respect Retry-After headers on 429 rate limits","Validate repository URLs and permissions up front"],"tags":["http","network","git","status-code","reqwest"],"backgroundTag":"http-error-response","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}