{"record":{"id":"31f62fbc6ea4e4ed","repo":"zed-industries/zed","slug":"oauth-authorization-failed","errorCode":null,"errorMessage":"OAuth authorization failed: {} ({})","messagePattern":"OAuth authorization failed: (.+?) \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/oauth_callback_server/src/oauth_callback_server.rs","lineNumber":206,"sourceCode":"                            state = Some(value.into_owned());\n                        }\n                    }\n                    \"error\" => {\n                        if !value.is_empty() {\n                            error = Some(value.into_owned());\n                        }\n                    }\n                    \"error_description\" => {\n                        if !value.is_empty() {\n                            error_description = Some(value.into_owned());\n                        }\n                    }\n                    _ => {}\n                }\n            }\n\n            if let Some(error_code) = error {\n                anyhow::bail!(\n                    \"OAuth authorization failed: {} ({})\",\n                    error_code,\n                    error_description.as_deref().unwrap_or(\"no description\")\n                );\n            }\n\n            let code = code.ok_or_else(|| anyhow!(\"missing 'code' parameter in OAuth callback\"))?;\n            let state =\n                state.ok_or_else(|| anyhow!(\"missing 'state' parameter in OAuth callback\"))?;\n\n            Ok(Self { code, state })\n        }\n    }\n\n    /// How long to wait for the browser to complete the OAuth flow before giving\n    /// up and releasing the loopback port.\n    const OAUTH_CALLBACK_TIMEOUT: Duration = Duration::from_secs(2 * 60);\n","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/oauth_callback_server/src/oauth_callback_server.rs#L188-L224","documentation":"Zed's local OAuth callback server parses the provider's redirect query string. Per the OAuth2 error-response convention (RFC 6749), presence of an `error` parameter means the authorization attempt itself failed; the code embeds it plus `error_description` (or 'no description' when absent) and never returns a code.","triggerScenarios":"The provider redirects back with error=access_denied (user clicked Deny/Cancel), invalid_client, invalid_request, or temporarily_unavailable in the query string — e.g. denying the consent screen, a mismatched client_id/secret, or a mismatched redirect URI registered with the provider.","commonSituations":"Cancelling the sign-in consent page; stale/incorrect client credentials configured for the integration; redirect URI registered in the provider app not matching the loopback callback; clock/state mismatches surfacing as invalid_request.","solutions":["Retry the sign-in and approve the consent screen — access_denied is usually just a cancelled flow","Verify the client_id/client_secret and registered redirect URI in the provider's app console match what Zed uses","Check error_description in the message for the provider's exact reason and act on that code","Re-start the OAuth flow to get a fresh state if the error mentions expired/invalid state"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before opening the browser, confirm provider app config\nfn provider_config_plausible(client_id: &str, redirect_uri: &Url) -> bool {\n    !client_id.is_empty() && redirect_uri.scheme() == \"http\" && redirect_uri.host_str() == Some(\"localhost\")\n}","typeGuard":null,"tryCatchPattern":"match OAuthCallbackParams::parse_query(query) {\n    Err(e) if e.to_string().contains(\"OAuth authorization failed\") => {\n        let code = extract_error_code(&e); // access_denied vs invalid_client\n        if code == \"access_denied\" {\n            show(\"Sign-in was cancelled\"); // benign, allow retry\n        } else {\n            show_provider_config_guidance(&e); // check client id / redirect URI\n        }\n    }\n    r => r?,\n}","preventionTips":["Register the exact loopback redirect URI in the provider app console","Treat access_denied as user cancellation, not an error state","Include the provider's error_description in diagnostics; it names the real cause","Start a fresh flow (new state) rather than replaying old authorize URLs"],"tags":["oauth","authentication","callback","authorization"],"backgroundTag":"oauth-authorization-denied","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}