{"record":{"id":"95525323dfaa2e22","repo":"Hmbown/CodeWhale","slug":"sign-in-was-not-completed-detail","errorCode":null,"errorMessage":"sign-in was not completed: {detail}","messagePattern":"sign-in was not completed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/oauth.rs","lineNumber":1241,"sourceCode":"                \"OAuth callback state did not match the pending login\"\n            );\n            Ok(code)\n        }\n        CallbackOutcome::Error {\n            error,\n            description,\n            state,\n        } => {\n            if let Some(state) = state {\n                anyhow::ensure!(\n                    state == expected_state,\n                    \"OAuth error callback state did not match the pending login\"\n                );\n            }\n            let detail = description\n                .filter(|text| !text.trim().is_empty())\n                .unwrap_or(error);\n            bail!(\"sign-in was not completed: {detail}\")\n        }\n    }\n}\n\nfn parse_http_request_target(request_line: &str) -> Result<String> {\n    let mut parts = request_line.split_whitespace();\n    let method = parts.next().unwrap_or_default();\n    anyhow::ensure!(\n        method.eq_ignore_ascii_case(\"GET\"),\n        \"OAuth callback must be GET\"\n    );\n    let target = parts\n        .next()\n        .context(\"OAuth callback missing request target\")?;\n    Ok(target.to_string())\n}\n\nfn query_from_target<'a>(params: &OAuthProviderParams, target: &'a str) -> Result<&'a str> {","sourceCodeStart":1223,"sourceCodeEnd":1259,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/oauth.rs#L1223-L1259","documentation":"The OAuth provider redirected back to the loopback callback with an `error` parameter (and optionally an `error_description`), so sign-in did not complete. The library surfaces the provider's description (or bare error code) to the user. This is how authorization failures like `access_denied` reach the caller.","triggerScenarios":"The browser callback hits the local listener with `?error=...`; the state matched the pending login but the provider reported an OAuth error — e.g. the user clicked 'Cancel'/'Deny' on the consent screen, the app is unapproved, or scopes were rejected.","commonSituations":"User denies the consent prompt; OAuth app not yet approved/installed on the provider tenant; requesting scopes the app isn't allowed; expired or reused sign-in attempt rejected by the provider.","solutions":["Read `detail` in the message — it names the provider-side OAuth error (e.g. `access_denied`).","Retry the sign-in and approve the consent screen when the browser opens.","Fix the app registration (approved scopes, allowed redirect URI `http://localhost:<port>`) on the provider, then sign in again."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match pkce_login(provider).await {\n    Ok(pending) => { /* proceed */ }\n    Err(e) if e.to_string().starts_with(\"sign-in was not completed\") => {\n        // surface provider detail, prompt user to retry and approve consent\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Complete the consent screen promptly when the browser opens.","Pre-approve the OAuth app's scopes/redirect URI on the provider.","Always start a fresh login rather than reusing an old state."],"tags":["oauth","callback","consent-denied"],"backgroundTag":"oauth-token-exchange-failed","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"}