zed-industries/zed · warning

OAuth callback was cancelled

Error message

OAuth callback was cancelled

What it means

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.

Solutions

  1. Keep the sign-in task alive until the browser flow completes or the user explicitly cancels.
  2. Treat as user cancellation: return control quietly instead of logging a hard error.
  3. Re-invoke sign_in to restart the flow — a new PKCE request and callback server are created each attempt.
  4. Add an explicit, longer timeout with a user-visible prompt rather than letting the task be silently cancelled.

Example fix

// before
let creds = sign_in(&http_client, cx).await?;
// after
match sign_in(&http_client, cx).await {
    Ok(creds) => creds,
    Err(e) if e.to_string().contains("OAuth callback was cancelled") => {
        log::info!("Sign-in cancelled by user");
        return Err(e);
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !signed_in_task_active() {
    log::info!("no active sign-in flow; callback server would be cancelled");
}

Type guard

fn is_oauth_cancelled(err: &anyhow::Error) -> bool {
    err.to_string().contains("OAuth callback was cancelled")
}

Try / catch

let creds = match sign_in(&http_client, cx).await {
    Ok(creds) => creds,
    Err(e) if is_oauth_cancelled(&e) => {
        log::info!("sign-in flow cancelled; not an error");
        return Ok(None);
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19). Data as JSON: /api/errors/46dba0f6269b413f. Report an issue: GitHub.

Appendix: source

Thrown at crates/x_ai_subscribed/src/x_ai_subscribed.rs:816

    cx: &AsyncApp,
) -> Result<SuperGrokCredentials> {
    let (redirect_uri, callback_rx) =
        oauth_callback_server::start_oauth_callback_server_with_config(
            oauth_callback_server::OAuthCallbackServerConfig {
                host: CALLBACK_HOST,
                preferred_port: CALLBACK_PORT,
                fallback_port: None,
                path: CALLBACK_PATH,
            },
        )
        .context("Failed to start OAuth callback server")?;

    let pkce = new_pkce_authorize_request(redirect_uri)?;
    cx.update(|cx| cx.open_url(&pkce.authorize_url));

    let callback = callback_rx
        .await
        .map_err(|_| anyhow!("OAuth callback was cancelled"))?
        .context("OAuth callback failed")?;

    if callback.state != pkce.state {
        return Err(anyhow!("OAuth state mismatch"));
    }

    let tokens = exchange_code(
        &http_client,
        &callback.code,
        &pkce.verifier,
        &pkce.redirect_uri,
    )
    .await
    .context("Token exchange failed")?;

    let refresh_token = tokens
        .refresh_token
        .filter(|token| !token.is_empty())

View on GitHub (pinned to 916fc2b8cb)