{"record":{"id":"417fe1bdad9412d9","repo":"lbjlaq/Antigravity-Manager","slug":"failed-to-build-oauth-url","errorCode":null,"errorMessage":"Failed to build OAuth URL","messagePattern":"Failed to build OAuth URL","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src-tauri/src/modules/oauth.rs","lineNumber":366,"sourceCode":"        (\"redirect_uri\", redirect_uri),\n        (\"response_type\", \"code\"),\n        (\"scope\", &scopes),\n        (\"access_type\", \"offline\"),\n        (\"prompt\", \"consent\"),\n        (\"include_granted_scopes\", \"true\"),\n        (\"state\", state),\n    ];\n\n    let url = url::Url::parse_with_params(AUTH_URL, &params)\n        .map_err(|e| format!(\"Invalid Auth URL: {}\", e))?;\n    Ok((url.to_string(), client.key))\n}\n\n/// Generate OAuth authorization URL using current active client.\npub fn get_auth_url(redirect_uri: &str, state: &str) -> String {\n    get_auth_url_with_client(redirect_uri, state, None)\n        .map(|(url, _)| url)\n        .expect(\"Failed to build OAuth URL\")\n}\n\nasync fn exchange_code_once(\n    code: &str,\n    redirect_uri: &str,\n    client_cfg: &OAuthClientConfig,\n) -> Result<TokenResponse, (Option<reqwest::StatusCode>, String)> {\n    // [PHASE 2] 对于登录行为，尚未有 account_id，使用全局池阶梯逻辑\n    let client = if let Some(pool) = crate::proxy::proxy_pool::get_global_proxy_pool() {\n        pool.get_effective_standard_client(None, 60).await\n    } else {\n        crate::utils::http::get_long_standard_client()\n    };\n\n    let params = [\n        (\"client_id\", client_cfg.client_id.as_str()),\n        (\"client_secret\", client_cfg.client_secret.as_str()),\n        (\"code\", code),","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/lbjlaq/Antigravity-Manager/blob/90a2b6b20797e2e593a83d0c54ab86037863fe70/src-tauri/src/modules/oauth.rs#L348-L384","documentation":"get_auth_url unwraps get_auth_url_with_client with expect, panicking with 'Failed to build OAuth URL' when URL construction fails (e.g. no active OAuth client configured or the client's endpoints are missing/invalid). It is a fatal invariant: the function's signature promises a String.","triggerScenarios":"Calling get_auth_url when no active OAuth client exists, when client_cfg fields (auth_url/client_id) are empty or malformed so Url::parse fails, or any Err from get_auth_url_with_client.","commonSituations":"App first-run without OAuth client config; config file edited and an endpoint URL broken; get_auth_url called before client initialization completes.","solutions":["Ensure an OAuth client is configured and set as active before calling get_auth_url","Validate client config fields (valid URLs, non-empty client_id) at load time","Refactor get_auth_url to return Result<String, Error> and propagate instead of expect/panic"],"exampleFix":"// before\npub fn get_auth_url(redirect_uri: &str, state: &str) -> String {\n    get_auth_url_with_client(redirect_uri, state, None)\n        .map(|(url, _)| url)\n        .expect(\"Failed to build OAuth URL\")\n}\n// after\npub fn get_auth_url(redirect_uri: &str, state: &str) -> Result<String, OAuthError> {\n    get_auth_url_with_client(redirect_uri, state, None)\n        .map(|(url, _)| url)\n        .map_err(|e| OAuthError::UrlBuild(e.to_string()))\n}","handlingStrategy":"validation","validationCode":"if let Err(e) = validate_client_config(&config) { return Err(format!(\"OAuth client misconfigured: {}\", e)); }","typeGuard":null,"tryCatchPattern":"let url = get_auth_url_with_client(uri, state, None).map(|(u, _)| u).map_err(|e| eprintln!(\"oauth url build failed: {e}\"))?;","preventionTips":["Validate OAuth client fields (URLs parse, ids non-empty) at config load","Never use expect in library-level code; return Result","Add a startup check that an active client exists before OAuth routes are exposed"],"tags":["rust","oauth","panic"],"backgroundTag":"missing-required-config","analyzedSha":"90a2b6b20797e2e593a83d0c54ab86037863fe70","analyzedAt":"2026-09-19T08:34:01.322Z","contentChangedAt":"2026-09-19T08:34:01.322Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}