{"record":{"id":"277f126f4ae5b354","repo":"Hmbown/CodeWhale","slug":"offers-no-browser-sign-in-flow","errorCode":null,"errorMessage":"{} offers no browser sign-in flow","messagePattern":"(.+?) offers no browser sign-in flow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/oauth.rs","lineNumber":1147,"sourceCode":"        let chunk = uuid::Uuid::new_v4();\n        let take = (bytes.len() - offset).min(16);\n        bytes[offset..offset + take].copy_from_slice(&chunk.as_bytes()[..take]);\n        offset += take;\n    }\n    URL_SAFE_NO_PAD.encode(bytes)\n}\n\npub fn build_authorize_url(\n    params: &OAuthProviderParams,\n    issuer: &str,\n    client_id: &str,\n    scopes: &str,\n    redirect_uri: &str,\n    state: &str,\n    pkce: &PkceChallenge,\n) -> Result<String> {\n    let Some(authorize_path) = params.authorize_path else {\n        bail!(\"{} offers no browser sign-in flow\", params.display_name);\n    };\n    // A malformed configured issuer must fail loudly. Silently redirecting\n    // the browser to the production authorize endpoint would hand the\n    // issuer a sign-in the user aimed somewhere else.\n    let issuer_var = params\n        .env\n        .issuer_vars\n        .first()\n        .copied()\n        .unwrap_or(\"the issuer environment variable\");\n    let mut url = oauth_endpoint_url(&format!(\n        \"{}/{}\",\n        issuer.trim_end_matches('/'),\n        authorize_path\n    ))\n    .with_context(|| {\n        format!(\n            \"{} OAuth issuer is not a valid URL or uses an insecure endpoint — check {issuer_var}\",","sourceCodeStart":1129,"sourceCodeEnd":1165,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/oauth.rs#L1129-L1165","documentation":"During the PKCE browser sign-in flow, the provider's parameter set has no `authorize_path`, meaning no authorization endpoint is defined for it. The library refuses to construct an authorize URL because the provider (e.g. xAI) simply does not support browser-based OAuth sign-in. This is a guard so the flow fails with a clear reason instead of building a malformed or missing URL.","triggerScenarios":"Calling the internal authorize-URL builder (the function taking `scopes`, `redirect_uri`, `state`, `pkce`) with an `OAuthProviderParams` whose `authorize_path` is `None` — i.e. a provider configured without a browser authorization endpoint, such as xAI.","commonSituations":"Running `codewhale` browser login against a provider that only supports device-code login; a provider config/registry entry missing `authorize_path`; wiring a custom provider params struct without setting `authorize_path`.","solutions":["Use the device-code login flow for this provider instead (e.g. `codewhale auth xai-device`).","Check `oauth_provider_params(provider)` for the chosen provider and pick one that defines `authorize_path`.","If you own a custom provider config, add the correct `authorize_path` for its issuer."],"exampleFix":"// before\ncodewhale auth login --provider xai   // browser flow, xAI has no authorize_path\n// after\ncodewhale auth xai-device             // device-code flow","handlingStrategy":"validation","validationCode":"let params = oauth_provider_params(provider);\nif params.authorize_path.is_none() {\n    // fall back to device-code flow instead of browser PKCE\n    return device_code_login(provider).await;\n}","typeGuard":"fn supports_browser_flow(params: &OAuthProviderParams) -> bool {\n    params.authorize_path.is_some()\n}","tryCatchPattern":null,"preventionTips":["Check `authorize_path` support before choosing the browser login command.","Use `codewhale auth xai-device` for xAI and other device-code-only providers.","Keep custom provider param entries complete (authorize_path set) if browser login is expected."],"tags":["oauth","browser-flow","unsupported-provider"],"backgroundTag":"unsupported-operation","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"}