{"record":{"id":"a8eb89d9721970f0","repo":"decolua/9router","slug":"failed-to-get-user-info-error-a8eb89","errorCode":null,"errorMessage":"Failed to get user info: ${error}","messagePattern":"Failed to get user info: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/github.js","lineNumber":138,"sourceCode":"    return await response.json();\n  }\n\n  /**\n   * Get user info using GitHub access token\n   */\n  async getUserInfo(accessToken) {\n    const response = await fetch(`${GITHUB_CONFIG.userInfoUrl}`, {\n      headers: {\n        Authorization: `Bearer ${accessToken}`, // GitHub API typically uses Bearer\n        Accept: \"application/json\",\n        \"X-GitHub-Api-Version\": GITHUB_CONFIG.apiVersion,\n        \"User-Agent\": GITHUB_CONFIG.userAgent,\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Failed to get user info: ${error}`);\n    }\n\n    return await response.json();\n  }\n\n  /**\n   * Complete GitHub Copilot authentication flow\n   */\n  async authenticate() {\n    try {\n      // Get device code\n      const deviceResponse = await this.getDeviceCode();\n      \n      // Poll for access token\n      const tokenResponse = await this.pollAccessToken(\n        deviceResponse.device_code, \n        deviceResponse.verification_uri, \n        deviceResponse.user_code","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/github.js#L120-L156","documentation":"GitHubService.getUserInfo() calls GET https://api.github.com/user with the freshly obtained access token to fetch the authenticated user's profile. A non-OK response causes the raw body to be thrown as `Failed to get user info: ${error}`. Since the token was just minted by the device flow, this usually indicates a network/API problem rather than bad credentials — but a revoked or scope-less token will also fail here with 401.","triggerScenarios":"GET to api.github.com/user returns non-2xx: 401 (bad/insufficiently-scoped token), 403 (rate limit exhausted for the IP), 5xx from GitHub, or an intercepted body from a proxy/portal.","commonSituations":"Shared IP (corporate NAT/CI) hitting GitHub's unauthenticated rate limits; a proxy stripping the Authorization header; GitHub API incident; User-Agent or X-GitHub-Api-Version rejected by an API gateway.","solutions":["Inspect the embedded body for a 403 rate-limit message; if so, wait for the rate-limit window or authenticate from a different IP.","Re-run the device-flow authentication to obtain a fresh token, then retry.","Verify api.github.com is reachable (curl -i https://api.github.com/user with the token) and no proxy strips Authorization.","Retry later if GitHub status (githubstatus.com) reports an API incident."],"exampleFix":"// before\nif (!response.ok) {\n  const error = await response.text();\n  throw new Error(`Failed to get user info: ${error}`);\n}\n// after\nif (!response.ok) {\n  const error = await response.text();\n  throw new Error(`Failed to get user info (HTTP ${response.status}): ${error}`);\n}","handlingStrategy":"retry","validationCode":"async function assertUserFetchable(accessToken) {\n  const res = await fetch('https://api.github.com/user', {\n    headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json', 'User-Agent': 'app' },\n  });\n  if (res.status === 403 && res.headers.get('x-ratelimit-remaining') === '0') {\n    throw new Error('GitHub API rate limit exhausted — wait for reset before authenticating');\n  }\n  if (!res.ok) throw new Error(`GitHub /user pre-check failed: HTTP ${res.status}`);\n}","typeGuard":"function isGitHubUser(data) {\n  return data !== null && typeof data === 'object' && typeof data.login === 'string' && typeof data.id === 'number';\n}","tryCatchPattern":"try {\n  const userInfo = await service.getUserInfo(accessToken);\n} catch (err) {\n  if (err.message.startsWith('Failed to get user info')) {\n    console.error('GitHub /user call failed — check rate limits (403), token validity (401), or api.github.com reachability, then retry.');\n  }\n  throw err;\n}","preventionTips":["Retry with backoff on 5xx and on 403 rate-limit responses (respect x-ratelimit-reset).","Run heavy automation from IPs not shared across many unauthenticated GitHub calls.","Confirm proxies don't strip the Authorization header when calling api.github.com.","Check githubstatus.com for API incidents before scheduled auth runs."],"tags":["network","http","github","rate-limit"],"backgroundTag":"github-api-rate-limit","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}