decolua/9router · error · Error
"Missing account email/phone in user info"
Error message
"Missing account email/phone in user info"
What it means
The iFlow user-info payload lacked any account identifier: neither email nor phone was present after trimming. The library requires one because mapTokens uses it as the account's identity (email field) for display and multi-account bookkeeping.
Source
Thrown at src/lib/oauth/providers/iflow.js:76
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) => ({
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
expiresIn: tokens.expires_in,
apiKey: extra?.userInfo?.apiKey,
email: extra?.userInfo?.email || extra?.userInfo?.phone,
displayName: extra?.userInfo?.nickname || extra?.userInfo?.name,
}),
};
export default iflow;
View on GitHub (pinned to 90b52e06ff)
Solutions
- Bind an email or phone number to the iFlow account in the iFlow console, then re-run the OAuth flow.
- Use a different iFlow account that has a verified email or phone attached.
- Inspect the raw userInfo JSON — if identifiers exist under different field names (e.g. account, userId), extend the lookup in iflow.js postExchange.
- If iFlow legitimately cannot supply an identifier, relax the validation and fall back to a derived name (e.g. nickname or 'iflow-<id>') when saving the account.
Example fix
// before
const email = userInfo.email?.trim() || userInfo.phone?.trim();
if (!email) {
throw new Error("Missing account email/phone in user info");
}
// after: accept alternative identifiers
const email = userInfo.email?.trim() || userInfo.phone?.trim() || userInfo.account?.trim();
if (!email) {
throw new Error("Missing account email/phone in user info (have: " + Object.keys(userInfo).join(',') + ")");
} Defensive patterns
Strategy: validation
Validate before calling
// verify the account carries an identifier before running the flow, or pre-inspect the payload
function hasAccountIdentifier(userInfo) {
const id = userInfo?.email?.trim() || userInfo?.phone?.trim();
return typeof id === 'string' && id.length > 0;
} Type guard
function isIdentifiableUserInfo(u) {
return typeof u === 'object' && u !== null
&& (typeof u.email === 'string' && u.email.trim() !== ''
|| typeof u.phone === 'string' && u.phone.trim() !== '');
} Try / catch
try {
const { userInfo } = await provider.postExchange(tokens);
} catch (e) {
if (e.message === 'Missing account email/phone in user info') {
return { ok: false, reason: 'no-identifier', hint: 'Bind an email or phone to the iFlow account, then retry login' };
}
throw e;
} Prevention
- Require accounts to have a bound email or phone before they use the OAuth import feature.
- If iFlow changes its user-info schema, log Object.keys(userInfo) on this failure to spot renamed identifier fields quickly.
- Consider accepting nickname/account-name fallbacks in your own wrapper if identifier-less accounts are legitimate in your deployment.
- Surface this error as an actionable message to the end user — it is fixable in the iFlow console, not in code.
When it happens
Trigger: postExchange computes email = userInfo.email?.trim() || userInfo.phone?.trim() and throws when both are falsy — accounts registered only with a username/OAuth identity (no email or phone bound), or a schema change removing those fields from result.data.
Common situations: iFlow accounts created via third-party login that never bound an email or phone; privacy-restricted accounts where iFlow omits contact fields; response schema drift moving email/phone into a nested object.
Related errors
- "Empty API key returned from iFlow"
- Missing Zed callback URL
- Invalid Zed callback URL
- Zed callback must include user_id and access_token
- Missing xAI authorization code
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/7f1910d884250f4c.
Report an issue: GitHub.