{"record":{"id":"20169cffe7f9d34f","repo":"yikart/AiToEarn","slug":"failed-to-fetch-user-info","errorCode":null,"errorMessage":"Failed to fetch user info","messagePattern":"Failed to fetch user info","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/plat/google/google.service.ts","lineNumber":822,"sourceCode":"  }\n\n  /**\n   * 获取已授权的用户信息\n   * @param data\n   */\n  async getUserInfo(accessToken: string, token) {\n    try {\n      const response = await axios.get('https://www.googleapis.com/oauth2/v3/userinfo', {\n        headers: {\n          Authorization: `Bearer ${accessToken}`,\n        },\n      });\n\n      // 返回用户信息\n      return response.data;\n    } catch (err) {\n      console.error('Error fetching user info:', err);\n      throw new Error('Failed to fetch user info');\n    }\n  }\n\n}\n\n\n","sourceCodeStart":804,"sourceCodeEnd":829,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/google/google.service.ts#L804-L829","documentation":"getUserInfo calls Google's userinfo endpoint with the user's access token and returns response.data. Any failure — 401 invalid/expired token, network error, malformed response — is caught and rethrown as Error('Failed to fetch user info'), so the caller only sees the generic message while the real cause is only visible in the console.error log.","triggerScenarios":"Calling getUserInfo with an access token that is expired, revoked, or missing required scopes (openid/email/profile), or when the HTTP request to the Google userinfo endpoint fails.","commonSituations":"Token expired between issuance and this call; scope not requested at consent time so userinfo returns 403/401; Google service outage; server egress blocked.","solutions":["Refresh the access token (refreshAccessToken) before calling getUserInfo if it may be expired","Confirm the OAuth consent request included openid, email and profile scopes","Check console.error output for the underlying HTTP status and Google error body","If the token is invalid_grant/revoked, require the user to reconnect the Google account","Return a structured 401/502 from the controller instead of the raw generic Error"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!accessToken || typeof accessToken !== 'string') {\n  throw new UnauthorizedException('Missing Google access token');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await googleService.getUserInfo(accessToken);\n} catch (err) {\n  const refreshed = await refreshAccessToken(account); // token likely expired\n  return await googleService.getUserInfo(refreshed.access_token);\n}","preventionTips":["Attempt a token refresh on 401 before surfacing the error","Request openid/email/profile scopes at consent time","Treat 401 as expired token, 403 as missing scope","Cache userinfo briefly to reduce API calls"],"tags":["google","oauth","userinfo","api-call"],"backgroundTag":"google-api-request-failed","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}