{"record":{"id":"e59465388ebe351a","repo":"zed-industries/zed","slug":"copilot-sign-in-failed-unexpected-response-from-g","errorCode":null,"errorMessage":"Copilot sign-in failed: unexpected response from GitHub","messagePattern":"Copilot sign-in failed: unexpected response from GitHub","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/copilot_chat/src/copilot_oauth.rs","lineNumber":135,"sourceCode":"        let mut response = client.send(request).await?;\n        let mut response_body = Vec::new();\n        response.body_mut().read_to_end(&mut response_body).await?;\n\n        let parsed: AccessTokenResponse = serde_json::from_slice(&response_body)\n            .context(\"Failed to parse GitHub access-token response\")?;\n\n        if let Some(token) = parsed.access_token {\n            return Ok(token);\n        }\n\n        match parsed.error.as_deref() {\n            Some(\"authorization_pending\") => continue,\n            // GitHub asks us to back off; increase the interval and keep polling.\n            Some(\"slow_down\") => interval += 5,\n            Some(\"expired_token\") => bail!(\"The Copilot sign-in code expired. Please try again.\"),\n            Some(\"access_denied\") => bail!(\"Copilot sign-in was cancelled.\"),\n            Some(other) => bail!(\"Copilot sign-in failed: {other}\"),\n            None => bail!(\"Copilot sign-in failed: unexpected response from GitHub\"),\n        }\n    }\n}\n\nfn form_encode(fields: &[(&str, &str)]) -> String {\n    fields\n        .iter()\n        .map(|(key, value)| format!(\"{}={}\", url_encode(key), url_encode(value)))\n        .collect::<Vec<_>>()\n        .join(\"&\")\n}\n\nfn url_encode(value: &str) -> String {\n    let mut encoded = String::with_capacity(value.len());\n    for byte in value.bytes() {\n        match byte {\n            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {\n                encoded.push(byte as char)","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/copilot_chat/src/copilot_oauth.rs#L117-L153","documentation":"The device-flow token response parsed successfully as JSON but contained neither an access_token nor an error field - the None arm of the match. Zed treats any such shape as 'unexpected response from GitHub' because the OAuth device-grant spec requires one of the two. It almost always indicates a response that is not really the OAuth endpoint's payload (proxy page, outage body) rather than a spec'd error.","triggerScenarios":"Polling https://github.com/login/oauth/access_token returns 200 with a body that is valid JSON yet lacks both access_token and error - e.g. an intercepting proxy returning an empty JSON object, a GitHub incident serving a stub body, or a custom github-enterprise host whose OAuth endpoints are misconfigured.","commonSituations":"Corporate TLS-inspecting proxies rewriting OAuth responses; GitHub Enterprise Server versions with different device-flow support; transient outage bodies; GITHUB_ENTERPRISE_URI misconfigured to a non-OAuth path.","solutions":["Retry the sign-in flow once to rule out a transient body","Inspect what host actually answered (proxy/enterprise override of the OAuth endpoint)","For GitHub Enterprise, verify the instance supports the device flow and its version is current","Bypass the proxy for github.com/login/oauth endpoints and retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match poll_for_token(/* .. */).await {\n    Ok(token) => Ok(token),\n    Err(err) if err.to_string().contains(\"unexpected response\") => {\n        // retry once with a fresh flow; if it repeats, report proxy/enterprise endpoint issues\n        retry_sign_in_once().await\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Ensure nothing between the client and github.com rewrites OAuth endpoint responses","For GitHub Enterprise, pin a verified OAuth base URI instead of guessing paths"],"tags":["copilot","oauth","device-flow","github","proxy","rust"],"backgroundTag":"oauth-malformed-response","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}