{"record":{"id":"6b084095f43f416b","repo":"gitroomhq/postiz-app","slug":"user-info-request-failed-error","errorCode":null,"errorMessage":"User info request failed: ${error}","messagePattern":"User info request failed: (.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/backend/src/services/auth/providers/oauth.provider.ts","lineNumber":89,"sourceCode":"      throw new Error(`Token request failed: ${error}`);\n    }\n\n    const { access_token } = await response.json();\n    return access_token;\n  }\n\n  async getUser(access_token: string): Promise<{ email: string; id: string }> {\n    const { userInfoUrl } = this.getConfig();\n    const response = await fetch(`${userInfoUrl}`, {\n      headers: {\n        Authorization: `Bearer ${access_token}`,\n        Accept: 'application/json',\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`User info request failed: ${error}`);\n    }\n\n    const { email, sub: id } = await response.json();\n    return { email, id };\n  }\n}\n","sourceCodeStart":71,"sourceCodeEnd":96,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/apps/backend/src/services/auth/providers/oauth.provider.ts#L71-L96","documentation":"Generic OAuth provider base class: after a successful token exchange, the provider's user-info endpoint returned a non-2xx when called with the access_token (Accept: application/json). The provider's error body is appended to the message.","triggerScenarios":"Calling the provider's userinfo URL with an access token that is expired, revoked, lacks the required scope, or was issued for a different app; also provider-side errors (rate limiting, API downtime).","commonSituations":"Token scope lacks email/profile so userinfo returns 403; access token TTL of seconds and exchange->userinfo latency exceeds it; provider app permissions not approved for the userinfo scope; provider API deprecation changing the userinfo URL.","solutions":["Check the embedded status/error: 401 -> token invalid (re-do flow), 403 -> missing scope/consent, 429/5xx -> retry with backoff","Verify the authorization request includes the scopes the userinfo endpoint requires (usually email/profile)","Confirm the userinfo URL in the provider config is current (providers do deprecate API versions)","Add a single retry with jitter for transient 5xx/429 responses"],"exampleFix":"// before — single attempt, any failure throws\nconst res = await fetch(userinfoUrl, { headers: { Authorization: `Bearer ${token}` } });\n\n// after — one guarded retry for transient failures\nlet res = await fetch(userinfoUrl, { headers });\nif (res.status >= 500 || res.status === 429) {\n  await sleep(1000);\n  res = await fetch(userinfoUrl, { headers });\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  const profile = await provider.getUser(token);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('User info request failed:')) {\n    const body = e.message.slice('User info request failed:'.length);\n    if (/(429|5xx|unavailable)/.test(body)) {\n      await sleep(1000);\n      return provider.getUser(token); // single retry\n    }\n  }\n  throw e;\n}","preventionTips":["Request email/profile scopes upfront","Call userinfo immediately after token exchange","Add one bounded retry for transient provider failures"],"tags":["oauth","userinfo","provider"],"backgroundTag":"oauth-userinfo-request-failed","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}