{"record":{"id":"46dba0f6269b413f","repo":"zed-industries/zed","slug":"oauth-callback-was-cancelled-x-ai-subscribed","errorCode":null,"errorMessage":"OAuth callback was cancelled","messagePattern":"OAuth callback was cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/x_ai_subscribed/src/x_ai_subscribed.rs","lineNumber":816,"sourceCode":"    cx: &AsyncApp,\n) -> Result<SuperGrokCredentials> {\n    let (redirect_uri, callback_rx) =\n        oauth_callback_server::start_oauth_callback_server_with_config(\n            oauth_callback_server::OAuthCallbackServerConfig {\n                host: CALLBACK_HOST,\n                preferred_port: CALLBACK_PORT,\n                fallback_port: None,\n                path: CALLBACK_PATH,\n            },\n        )\n        .context(\"Failed to start OAuth callback server\")?;\n\n    let pkce = new_pkce_authorize_request(redirect_uri)?;\n    cx.update(|cx| cx.open_url(&pkce.authorize_url));\n\n    let callback = callback_rx\n        .await\n        .map_err(|_| anyhow!(\"OAuth callback was cancelled\"))?\n        .context(\"OAuth callback failed\")?;\n\n    if callback.state != pkce.state {\n        return Err(anyhow!(\"OAuth state mismatch\"));\n    }\n\n    let tokens = exchange_code(\n        &http_client,\n        &callback.code,\n        &pkce.verifier,\n        &pkce.redirect_uri,\n    )\n    .await\n    .context(\"Token exchange failed\")?;\n\n    let refresh_token = tokens\n        .refresh_token\n        .filter(|token| !token.is_empty())","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/zed-industries/zed/blob/916fc2b8cb3a815cbef4a3b40e13081be72036b6/crates/x_ai_subscribed/src/x_ai_subscribed.rs#L798-L834","documentation":"Raised in do_oauth_flow when the channel receiving the OAuth redirect from the local callback server yields Err — i.e. the receiver was dropped/cancelled before any callback arrived. The library opens the browser at the authorize URL and awaits callback_rx; if the async operation awaiting it is cancelled (task dropped, sign-in aborted) the recv fails and this error is produced. It signals the handshake never completed rather than that the callback itself failed.","triggerScenarios":"The future returned by do_oauth_flow (invoked via sign_in) is dropped or aborted while awaiting callback_rx after the browser has been opened; the user (or code) cancels sign-in, or the enclosing task is detached-then-cancelled / the app shuts down mid-flow.","commonSituations":"User closes the sign-in dialog or navigates away without completing the browser login; a timeout wrapper cancels the flow; application quits while the OAuth window is open.","solutions":["Keep the sign-in task alive until the browser flow completes or the user explicitly cancels.","Treat as user cancellation: return control quietly instead of logging a hard error.","Re-invoke sign_in to restart the flow — a new PKCE request and callback server are created each attempt.","Add an explicit, longer timeout with a user-visible prompt rather than letting the task be silently cancelled."],"exampleFix":"// before\nlet creds = sign_in(&http_client, cx).await?;\n// after\nmatch sign_in(&http_client, cx).await {\n    Ok(creds) => creds,\n    Err(e) if e.to_string().contains(\"OAuth callback was cancelled\") => {\n        log::info!(\"Sign-in cancelled by user\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"if !signed_in_task_active() {\n    log::info!(\"no active sign-in flow; callback server would be cancelled\");\n}","typeGuard":"fn is_oauth_cancelled(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"OAuth callback was cancelled\")\n}","tryCatchPattern":"let creds = match sign_in(&http_client, cx).await {\n    Ok(creds) => creds,\n    Err(e) if is_oauth_cancelled(&e) => {\n        log::info!(\"sign-in flow cancelled; not an error\");\n        return Ok(None);\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Hold the sign-in future (detach or store the task) until completion or explicit user cancel","Avoid wrapping sign_in in short timeouts that abort the browser round-trip","Always restart via sign_in rather than reusing a dead callback channel","Log cancellation at info level so users aren't shown spurious errors"],"tags":["oauth","cancelled","async","sign-in"],"backgroundTag":"oauth-callback-cancelled","analyzedSha":"916fc2b8cb3a815cbef4a3b40e13081be72036b6","analyzedAt":"2026-09-19T19:09:50.599Z","contentChangedAt":"2026-09-19T19:09:50.599Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}