decolua/9router · error · Error
`User info request failed: ${result.message || 'Unknown erro
Error message
`User info request failed: ${result.message || 'Unknown error'}` What it means
The iFlow user-info endpoint returned HTTP 200 but the JSON body has success: false, indicating an application-level rejection rather than an HTTP error. The provider's `message` field (or 'Unknown error') is included in the thrown error. This is iFlow's envelope convention: HTTP 200 does not imply success.
Source
Thrown at src/lib/oauth/providers/iflow.js:63
postExchange: async (tokens) => {
// Fetch user info (MUST succeed to get API key)
const userInfoRes = await fetch(
`${IFLOW_CONFIG.userInfoUrl}?accessToken=${encodeURIComponent(tokens.access_token)}`,
{
headers: {
Accept: "application/json",
},
}
);
if (!userInfoRes.ok) {
const errorText = await userInfoRes.text();
throw new Error(`Failed to fetch user info: ${errorText}`);
}
const result = await userInfoRes.json();
if (!result.success) {
throw new Error(`User info request failed: ${result.message || 'Unknown error'}`);
}
const userInfo = result.data || {};
// Validate API key (critical for iFlow)
if (!userInfo.apiKey || userInfo.apiKey.trim() === "") {
throw new Error("Empty API key returned from iFlow");
}
// Validate email/phone
const email = userInfo.email?.trim() || userInfo.phone?.trim();
if (!email) {
throw new Error("Missing account email/phone in user info");
}
return { userInfo };
},
mapTokens: (tokens, extra) => ({View on GitHub (pinned to 90b52e06ff)
Solutions
- Read result.message in the error text — it names the provider-side reason (e.g. token invalid, account restricted) and fix accordingly.
- Re-run the OAuth flow for a fresh access token if the message indicates token invalidity/expiry.
- Check the iFlow account's standing/plan in the iFlow console if the message indicates restrictions.
- If the message is always 'Unknown error', log the full result JSON — the response schema likely changed and the success/message fields moved.
Example fix
// before
if (!result.success) {
throw new Error(`User info request failed: ${result.message || 'Unknown error'}`);
}
// after: include full payload for diagnosing schema drift
if (!result.success) {
throw new Error(`User info request failed: ${result.message || 'Unknown error'} :: ${JSON.stringify(result).slice(0, 500)}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// HTTP 200 with success:false cannot be pre-validated, but you can pre-parse defensively
function parseUserInfoEnvelope(jsonText) {
try {
const r = JSON.parse(jsonText);
return r && typeof r === 'object' ? r : null;
} catch { return null; }
} Type guard
function isSuccessEnvelope(r) {
return r !== null && typeof r === 'object' && r.success === true && (r.data === undefined || typeof r.data === 'object');
} Try / catch
try {
const { userInfo } = await provider.postExchange(tokens);
} catch (e) {
const m = String(e.message).match(/^User info request failed: (.+?)(?: ::|$)/);
if (m) {
console.error('iFlow user-info rejected:', m[1]);
if (/token|expired|invalid/i.test(m[1])) return restartAuthFlow(); // provider-level token rejection
throw new Error(`iFlow account issue: ${m[1]}`); // restriction/provisioning problem
}
throw e;
} Prevention
- Never assume HTTP 200 means success with iFlow — always branch on the success field.
- Log the entire response envelope when success is falsy so schema drift or new message variants are visible.
- Treat messages mentioning token/expiry as restart-the-flow signals, not retry signals.
- Add a regression test that feeds a success:false fixture through postExchange.
When it happens
Trigger: userInfoRes.ok is true but result.success is falsy — e.g. the access token is expired/revoked but the API still answers 200, account is banned or not provisioned for iFlow coding, or the userInfoUrl path changed and returns a 200 error envelope.
Common situations: Expired-but-200-wrapped token responses; account restrictions (region, plan) that surface as success:false with a message; iFlow API version change that renamed success/message fields, making this check misfire; hitting the endpoint with a token from the wrong environment.
Related errors
- Failed to get user info
- Zed did not return an LLM token
- `Failed to fetch user info: ${errorText}`
- "Empty API key returned from iFlow"
- "Missing account email/phone in user info"
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/7e2c4ca19a7ac1b6.
Report an issue: GitHub.