{"record":{"id":"0cd1b0ccdca4e5b0","repo":"zed-industries/zed","slug":"token-refresh-failed-http-body","errorCode":null,"errorMessage":"Token refresh failed (HTTP {}): {body}","messagePattern":"Token refresh failed \\(HTTP (.+?)\\): (.+?)","errorType":"http","errorClass":"RefreshError::Fatal","httpStatus":null,"severity":"error","filePath":"crates/openai_subscribed/src/openai_subscribed.rs","lineNumber":1255,"sourceCode":") -> Result<CodexCredentials, RefreshError> {\n    let body = form_urlencoded::Serializer::new(String::new())\n        .append_pair(\"grant_type\", \"refresh_token\")\n        .append_pair(\"client_id\", CLIENT_ID)\n        .append_pair(\"refresh_token\", refresh_token)\n        .finish();\n\n    let request = HttpRequest::builder()\n        .method(Method::POST)\n        .uri(OPENAI_TOKEN_URL)\n        .header(\"Content-Type\", \"application/x-www-form-urlencoded\")\n        .body(AsyncBody::from(body))\n        .map_err(|e| RefreshError::Transient(e.into()))?;\n\n    let mut response = client\n        .send(request)\n        .await\n        .map_err(|e| RefreshError::Transient(e))?;\n    let status = response.status();\n    let mut body = String::new();\n    smol::io::AsyncReadExt::read_to_string(response.body_mut(), &mut body)\n        .await\n        .map_err(|e| RefreshError::Transient(e.into()))?;\n\n    if !status.is_success() {\n        let err = anyhow!(\"Token refresh failed (HTTP {}): {body}\", status);\n        // 400/401/403 indicate a revoked or invalid refresh token.\n        // 5xx and other errors are treated as transient.\n        if status == http_client::StatusCode::BAD_REQUEST\n            || status == http_client::StatusCode::UNAUTHORIZED\n            || status == http_client::StatusCode::FORBIDDEN\n        {\n            return Err(RefreshError::Fatal(err));\n        }\n        return Err(RefreshError::Transient(err));\n    }\n","sourceCodeStart":1237,"sourceCodeEnd":1273,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/openai_subscribed/src/openai_subscribed.rs#L1237-L1273","documentation":"The refresh-token grant at OPENAI_TOKEN_URL returned a non-success HTTP status. The code path classifies transport failures as RefreshError::Transient, and this HTTP failure similarly means the refresh did not complete; a 400/401 usually means the refresh token itself is expired or revoked and re-authentication is required.","triggerScenarios":"Thrown at crates/openai_subscribed/src/openai_subscribed.rs:1223 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["If the body indicates an invalid_grant, sign out and complete a fresh interactive sign-in — refresh tokens are single-use or expired","For 5xx or network-level statuses, retry the refresh after a delay","Check the OpenAI status page for auth endpoint outages"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5a9b9558db01a6b906cec2fb70a797affdc58cdd","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}