{"record":{"id":"98d5af8fa9fc60a6","repo":"decolua/9router","slug":"failed-to-get-user-info","errorCode":null,"errorMessage":"Failed to get user info","messagePattern":"Failed to get user info","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/iflow.js","lineNumber":86,"sourceCode":"  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`, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${token}`,\n        \"X-User-Id\": userId,\n      },","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/iflow.js#L68-L104","documentation":"Thrown by IFlowService.getUserInfo() when the user-info endpoint returns HTTP 200 but the JSON envelope has `success: false`. iFlow wraps payloads in { success, data }; a 200 with success:false means the request was transport-fine but the service refused to return profile data (e.g. the accessToken query parameter was rejected). Note this generic variant carries no upstream detail.","triggerScenarios":"getUserInfo(accessToken) receives an HTTP 200 whose body parses to { success: false } — typically an access token that is syntactically accepted but not authorized for the profile endpoint, an empty/garbage token string, or an API change where the envelope field was renamed.","commonSituations":"Passing the wrong token field from the exchange response (e.g. id_token instead of access_token); iFlow deprecating the `success` envelope without the CLI being updated; token from a different iFlow environment (staging vs prod).","solutions":["Log/inspect the full response body to see iFlow's actual reason field alongside success:false.","Confirm you pass tokens.access_token (not another field) into getUserInfo.","Re-run connect() to get a fresh token; the current one may be effectively revoked.","Check whether iFlow changed its response envelope and update the check accordingly."],"exampleFix":"// before\nif (!result.success) {\n  throw new Error(\"Failed to get user info\");\n}\n// after\nif (!result.success) {\n  throw new Error(`Failed to get user info: ${result.message || result.error || JSON.stringify(result).slice(0, 200)}`);\n}","handlingStrategy":"validation","validationCode":"// Pre-check the token before trusting the envelope-based endpoint\nfunction looksLikeJwt(token) {\n  return typeof token === \"string\" && token.split(\".\").length >= 2;\n}\nif (!looksLikeJwt(tokens.access_token)) throw new Error(\"access_token malformed — wrong field from exchange response?\");","typeGuard":"function isSuccessfulUserInfo(result) {\n  return result !== null && typeof result === \"object\" && result.success === true && result.data != null;\n}","tryCatchPattern":"try {\n  const userInfo = await iflowService.getUserInfo(tokens.access_token);\n} catch (err) {\n  if (err.message === \"Failed to get user info\") {\n    console.error(\"iFlow returned success:false with no detail — inspect the raw response and token field used.\");\n  } else { throw err; }\n}","preventionTips":["Verify you pass the correct exchange-response field (access_token) to getUserInfo.","Log the full envelope on success:false so the upstream reason isn't lost.","Re-run connect() after any token-related failure instead of retrying with the same token.","Track iFlow API changes to the { success, data } envelope."],"tags":["oauth","user-info","api-response"],"backgroundTag":"api-response-envelope-error","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}