gitroomhq/postiz-app · error · Error
User info request failed: ${error}
Error message
User info request failed: ${error} What it means
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.
Source
Thrown at apps/backend/src/services/auth/providers/oauth.provider.ts:89
throw new Error(`Token request failed: ${error}`);
}
const { access_token } = await response.json();
return access_token;
}
async getUser(access_token: string): Promise<{ email: string; id: string }> {
const { userInfoUrl } = this.getConfig();
const response = await fetch(`${userInfoUrl}`, {
headers: {
Authorization: `Bearer ${access_token}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const error = await response.text();
throw new Error(`User info request failed: ${error}`);
}
const { email, sub: id } = await response.json();
return { email, id };
}
}
View on GitHub (pinned to 0f1647f749)
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
Example fix
// before — single attempt, any failure throws
const res = await fetch(userinfoUrl, { headers: { Authorization: `Bearer ${token}` } });
// after — one guarded retry for transient failures
let res = await fetch(userinfoUrl, { headers });
if (res.status >= 500 || res.status === 429) {
await sleep(1000);
res = await fetch(userinfoUrl, { headers });
} Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try {
const profile = await provider.getUser(token);
} catch (e) {
if (e instanceof Error && e.message.startsWith('User info request failed:')) {
const body = e.message.slice('User info request failed:'.length);
if (/(429|5xx|unavailable)/.test(body)) {
await sleep(1000);
return provider.getUser(token); // single retry
}
}
throw e;
} Prevention
- Request email/profile scopes upfront
- Call userinfo immediately after token exchange
- Add one bounded retry for transient provider failures
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Organization not found
- Invalid user
- Token request failed: ${error}
- Token request failed: ${error}
- Integration not allowed
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/6b084095f43f416b.
Report an issue: GitHub.