{"record":{"id":"1796121ca973b3fd","repo":"decolua/9router","slug":"failed-to-get-user-info-error-179612","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/iflow.js","lineNumber":80,"sourceCode":"    return await response.json();\n  }\n\n  /**\n   * Get user info from iFlow\n   */\n  async getUserInfo(accessToken) {\n    const response = await fetch(\n      `${this.config.userInfoUrl}?accessToken=${encodeURIComponent(accessToken)}`,\n      {\n        headers: {\n          Accept: \"application/json\",\n        },\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    const result = await response.json();\n\n    if (!result.success) {\n      throw new Error(\"Failed to get user info\");\n    }\n\n    return result.data;\n  }\n\n  /**\n   * Save iFlow tokens to server\n   */\n  async saveTokens(tokens, userInfo) {\n    const { server, token, userId } = getServerCredentials();\n\n    const response = await fetch(`${server}/api/cli/providers/iflow`, {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/iflow.js#L62-L98","documentation":"Thrown by IFlowService.getUserInfo() when the iFlow user-info endpoint returns a non-OK HTTP status. The raw response text is embedded in the message. This happens after a successful token exchange, so the access token exists but the user-info call rejected it or the endpoint itself failed.","triggerScenarios":"getUserInfo(accessToken) is called and the server answers 401/403 (token invalid, expired, or lacking scope for user info), 404 (userInfoUrl changed), or 5xx (upstream outage); also when a proxy intercepts and returns an HTML error page.","commonSituations":"iFlow access token already invalid despite the exchange succeeding (clock skew, token type mismatch); userInfoUrl in IFLOW_CONFIG outdated after an API change; corporate proxy blocking the endpoint; rate limiting returning 429.","solutions":["Inspect the embedded body in the message for the actual status/cause (401/403 → token problem, 404 → endpoint changed).","Verify the access token from exchangeCode is the one iFlow expects (access_token vs apikey field mix-up).","Check IFLOW_CONFIG.userInfoUrl against current iFlow API docs — the endpoint may have moved.","Retry after a short wait if the message indicates 429/5xx.","Restart the full connect() flow to obtain a fresh token."],"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":"try-catch","validationCode":"// Check the token looks usable before calling user info\nif (!accessToken || typeof accessToken !== \"string\" || accessToken.length < 10) {\n  throw new Error(\"Refusing to call getUserInfo with a missing/short access token\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  const userInfo = await iflowService.getUserInfo(tokens.access_token);\n} catch (err) {\n  if (/Failed to get user info/.test(err.message)) {\n    if (/401|403|Unauthorized|Forbidden/i.test(err.message)) {\n      console.error(\"Token rejected for user info — obtain a fresh token via connect().\");\n    } else if (/404|Not Found/i.test(err.message)) {\n      console.error(\"userInfoUrl changed — update IFLOW_CONFIG.userInfoUrl.\");\n    }\n  } else { throw err; }\n}","preventionTips":["Always pass tokens.access_token from the exchange response, not another field.","Keep IFLOW_CONFIG.userInfoUrl current with iFlow's API.","Handle 429/5xx with a short backoff retry before failing.","Test from the same network the CLI will run on (proxies/VPNs alter responses)."],"tags":["oauth","http","network","user-info"],"backgroundTag":"http-request-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}