{"record":{"id":"314aa6aa29cf8616","repo":"zed-industries/zed","slug":"token-exchange-failed-http-body","errorCode":null,"errorMessage":"Token exchange failed (HTTP {}): {body}","messagePattern":"Token exchange failed \\(HTTP (.+?)\\): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openai_subscribed/src/openai_subscribed.rs","lineNumber":1218,"sourceCode":"async fn exchange_code(\n    client: &Arc<dyn HttpClient>,\n    code: &str,\n    verifier: &str,\n    redirect_uri: &str,\n) -> Result<TokenResponse> {\n    let body = form_urlencoded::Serializer::new(String::new())\n        .append_pair(\"grant_type\", \"authorization_code\")\n        .append_pair(\"client_id\", CLIENT_ID)\n        .append_pair(\"code\", code)\n        .append_pair(\"redirect_uri\", redirect_uri)\n        .append_pair(\"code_verifier\", verifier)\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\n    let mut response = client.send(request).await?;\n    let mut body = String::new();\n    smol::io::AsyncReadExt::read_to_string(response.body_mut(), &mut body).await?;\n\n    if !response.status().is_success() {\n        return Err(anyhow!(\n            \"Token exchange failed (HTTP {}): {body}\",\n            response.status()\n        ));\n    }\n\n    serde_json::from_str::<TokenResponse>(&body).context(\"Failed to parse token response\")\n}\n\nasync fn refresh_token(\n    client: &Arc<dyn HttpClient>,\n    refresh_token: &str,","sourceCodeStart":1200,"sourceCodeEnd":1236,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/openai_subscribed/src/openai_subscribed.rs#L1200-L1236","documentation":"The OAuth authorization-code exchange at OPENAI_TOKEN_URL returned a non-success HTTP status, so the code could not be redeemed for tokens. The status and body are included; typical causes are an expired/already-used authorization code, a PKCE verifier mismatch, or a redirect_uri mismatch.","triggerScenarios":"Thrown at crates/openai_subscribed/src/openai_subscribed.rs:1186 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Restart the sign-in flow — authorization codes are single-use and expire within minutes","Check that the system clock is accurate; skewed clocks invalidate code exchange","Verify redirect_uri and client_id match those registered with the provider"],"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"}