{"record":{"id":"ac0dc6ff891202b6","repo":"jlcodes99/cockpit-tools","slug":"error-ac0dc6","errorCode":null,"errorMessage":"获取用户信息失败: {}","messagePattern":"获取用户信息失败: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/commands/oauth.rs","lineNumber":77,"sourceCode":"    modules::logger::log_info(\"OAuth 授权成功，检查 refresh_token...\");\n\n    let refresh_token = token_res.refresh_token.ok_or_else(|| {\n        let msg = \"未获取到 Refresh Token。\\n\\n\\\n         可能原因：您之前已授权过此应用\\n\\n\\\n         解决方案：\\n\\\n         1. 访问 https://myaccount.google.com/permissions\\n\\\n         2. 撤销 'Antigravity Tools' 的访问权限\\n\\\n         3. 重新进行 OAuth 授权\"\n            .to_string();\n        modules::logger::log_error(&msg);\n        msg\n    })?;\n\n    modules::logger::log_info(\"获取用户信息...\");\n    let user_info = modules::oauth::get_user_info(&token_res.access_token)\n        .await\n        .map_err(|e| {\n            modules::logger::log_error(&format!(\"获取用户信息失败: {}\", e));\n            e\n        })?;\n\n    modules::logger::log_info(&format!(\n        \"用户: {} ({})\",\n        user_info.email,\n        user_info.name.as_deref().unwrap_or(\"无名称\")\n    ));\n\n    let token_data = models::TokenData::new(\n        token_res.access_token,\n        refresh_token,\n        token_res.expires_in,\n        Some(user_info.email.clone()),\n        None,\n        user_info.id.clone(),\n    )\n    .with_oauth_metadata(token_res.oauth_client_key, token_res.id_token);","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/commands/oauth.rs#L59-L95","documentation":"After obtaining OAuth tokens, start_oauth_login calls modules::oauth::get_user_info(&token_res.access_token) to fetch the Google account profile (email, display name). This error is logged and returned when that userinfo API call fails, aborting account creation since the account is keyed by email.","triggerScenarios":"get_user_info(access_token) returns Err: the userinfo endpoint returned 401/403 (invalid or insufficient-scope access token), a network/timeout error, or an unparseable response.","commonSituations":"OAuth scope not including userinfo.profile/userinfo.email so Google rejects the userinfo call; access token already expired or revoked by the time the call runs; offline/proxy/network interruption; Google userinfo endpoint outage.","solutions":["Check that the OAuth request includes the userinfo.email and userinfo.profile scopes, then re-run authorization","Verify network connectivity / proxy settings and retry the login","Check the wrapped error detail: 401 means re-authenticate; 403 means missing scope; 5xx/timeout means retry later","Confirm the access token is used promptly after exchange and not cached stale"],"exampleFix":"// before\nlet user_info = modules::oauth::get_user_info(&token_res.access_token)\n    .await\n    .map_err(|e| {\n        modules::logger::log_error(&format!(\"获取用户信息失败: {}\", e));\n        e\n    })?;\n// after\nlet user_info = modules::oauth::get_user_info(&token_res.access_token)\n    .await\n    .map_err(|e| {\n        modules::logger::log_error(&format!(\"获取用户信息失败: {}\", e));\n        if e.contains(\"401\") || e.contains(\"403\") {\n            format!(\"访问令牌无效或权限不足，请重新授权: {}\", e)\n        } else {\n            format!(\"获取用户信息失败，请检查网络后重试: {}\", e)\n        }\n    })?;","handlingStrategy":"retry","validationCode":"// ensure the token exchange requested the scopes needed for userinfo\nif !granted_scopes.contains(\"userinfo.email\") || !granted_scopes.contains(\"userinfo.profile\") {\n    return Err(\"授权缺少 userinfo 权限，请重新授权并勾选完整权限\".to_string());\n}","typeGuard":null,"tryCatchPattern":"let user_info = match modules::oauth::get_user_info(&token_res.access_token).await {\n    Ok(u) => u,\n    Err(e) if is_auth_error(&e) => return Err(format!(\"访问令牌无效或权限不足，请重新授权: {}\", e)),\n    Err(e) if is_transient(&e) => match modules::oauth::get_user_info(&token_res.access_token).await {\n        Ok(u) => u,\n        Err(e2) => return Err(format!(\"获取用户信息失败，请检查网络后重试: {}\", e2)),\n    },\n    Err(e) => return Err(format!(\"获取用户信息失败: {}\", e)),\n};","preventionTips":["Include userinfo.email and userinfo.profile scopes in the OAuth request","Use the access token promptly after exchange before it expires","Check proxy/DNS if userinfo calls consistently fail","Distinguish 401 (re-auth) from 403 (scope) from 5xx (retry) in error handling"],"tags":["oauth","google","userinfo","api-call"],"backgroundTag":"userinfo-fetch-failed","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}