{"record":{"id":"f57a6b95c764b9cb","repo":"zed-industries/zed","slug":"copilot-sign-in-was-cancelled","errorCode":null,"errorMessage":"Copilot sign-in was cancelled.","messagePattern":"Copilot sign-in was cancelled\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/copilot_chat/src/copilot_oauth.rs","lineNumber":133,"sourceCode":"            .body(AsyncBody::from(body.clone()))?;\n\n        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 {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/copilot_chat/src/copilot_oauth.rs#L115-L151","documentation":"GitHub's device-flow token endpoint returned error='access_denied', which Zed translates to 'Copilot sign-in was cancelled.' This means the authorization request was actively denied rather than expired - most commonly the user clicked 'Cancel' on GitHub's consent screen, or an org's OAuth policy blocked the app.","triggerScenarios":"Polling receives access_denied after the user rejects the Copilot OAuth app authorization on github.com, cancels the consent prompt, or the GitHub organization restricts third-party OAuth apps so consent auto-denies.","commonSituations":"Users clicking through GitHub consent screens too quickly; org-managed accounts with OAuth app allow-lists; re-trying sign-in after previously denying and expecting it to succeed without re-consent.","solutions":["Restart sign-in and approve the GitHub Copilot OAuth app when prompted","If on an org account: ask an org owner to approve/allow the Copilot OAuth application","Check github.com/settings/applications for a previously denied state"],"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(\"cancelled\") => {\n        // user-denied: return a non-error UI state prompting retry, not a crash\n        Ok(None)\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Treat access_denied as a user choice: show a friendly retry prompt, never a generic failure","If org OAuth policies block the app, surface that hint when the denial repeats"],"tags":["copilot","oauth","device-flow","github","access-denied","rust"],"backgroundTag":"oauth-access-denied","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}