{"record":{"id":"a00a5d7897717db6","repo":"Hmbown/CodeWhale","slug":"oauth-login-was-cancelled","errorCode":null,"errorMessage":"OAuth login was cancelled","messagePattern":"OAuth login was cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/tui/src/mcp/oauth.rs","lineNumber":1097,"sourceCode":"        perform_oauth_login_for_server_inner(\n            name,\n            server,\n            explicit_scopes,\n            callback_port,\n            callback_url,\n            network_policy,\n        ),\n    )\n    .await\n}\n\nasync fn run_cancellable_oauth<F, T>(cancellation_token: &CancellationToken, future: F) -> Result<T>\nwhere\n    F: std::future::Future<Output = Result<T>>,\n{\n    tokio::select! {\n        biased;\n        _ = cancellation_token.cancelled() => bail!(\"OAuth login was cancelled\"),\n        result = future => result,\n    }\n}\n\n/// Shared gate + scope resolution for `/mcp login` and the model-driven\n/// authenticate tool: URL-based servers only, no manual Authorization config,\n/// scopes from explicit argument, config, or discovery (in that order).\nasync fn resolve_oauth_login(\n    name: &str,\n    server: &McpServerConfig,\n    explicit_scopes: Option<Vec<String>>,\n    network_policy: Option<&NetworkPolicyDecider>,\n) -> Result<(String, ResolvedMcpOAuthScopes)> {\n    let Some(url) = server.url.as_deref() else {\n        bail!(\"OAuth login is only supported for URL-based MCP servers\");\n    };\n    if server_has_manual_authorization(server) {\n        bail!(\"MCP server '{name}' already has bearer/static Authorization configured\");","sourceCodeStart":1079,"sourceCodeEnd":1115,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp/oauth.rs#L1079-L1115","documentation":"run_cancellable_oauth wraps an OAuth login future with a cancellation token; when cancellation fires before the future completes, it aborts the flow and returns this error. It is a normal, expected outcome of a user or caller cancelling an in-progress MCP OAuth login, not a malfunction.","triggerScenarios":"Cancelling an in-flight OAuth login: pressing the cancel key in the /mcp login UI, dropping the authenticate tool call, or triggering the CancellationToken passed to perform_oauth_login_for_server_with_cancel while the browser-based flow is pending.","commonSituations":"User closes the login dialog or navigates away before completing the browser authorization; a timeout-driven cancel; the client shuts down mid-login; user retries the login, cancelling the previous attempt.","solutions":["Nothing is broken — simply run the OAuth login again and complete the browser authorization step","If cancellations happen unexpectedly, check for UI shutdowns, tool-call timeouts, or duplicate login invocations cancelling each other","Complete the browser authorization promptly after starting login to avoid cancelling flows","Verify no automation is issuing competing login requests for the same server"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match perform_oauth_login_for_server(&server).await {\n    Err(e) if e.to_string() == \"OAuth login was cancelled\" => {\n        eprintln!(\"login cancelled; rerun /mcp login to retry\");\n    }\n    other => other?,\n}","preventionTips":["Treat cancellation as a normal outcome, not an error to alert on","Avoid issuing duplicate login calls that cancel in-flight attempts","Complete browser authorization promptly","Only cancel via the dedicated CancellationToken, never by dropping tasks implicitly"],"tags":["oauth","mcp","cancelled","async"],"backgroundTag":"operation-cancelled","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}