decolua/9router · error · Error
"Empty API key returned from iFlow"
Error message
"Empty API key returned from iFlow"
What it means
The iFlow user-info call succeeded but result.data contains no usable apiKey (missing, null, or whitespace-only). iFlow accounts authenticate downstream API calls with this key, so the OAuth flow aborts rather than saving a credential that cannot work.
Source
Thrown at src/lib/oauth/providers/iflow.js:70
},
}
);
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) => ({
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,
}),View on GitHub (pinned to 90b52e06ff)
Solutions
- Log in to the iFlow console and confirm/generate an API key for the account, then retry the OAuth flow.
- If data was empty entirely, dump the raw user-info JSON — a schema change (renamed field) is likely; update the lookup accordingly.
- Verify the account is eligible for API access in its region/plan; upgrade or switch accounts if iFlow withholds keys.
- Retry the flow — occasionally keys are provisioned asynchronously right after account activation.
Example fix
// before
const userInfo = result.data || {};
if (!userInfo.apiKey || userInfo.apiKey.trim() === "") {
throw new Error("Empty API key returned from iFlow");
}
// after: distinguish missing-data vs missing-key
const userInfo = result.data;
if (!userInfo) {
throw new Error(`iFlow user info missing data field: ${JSON.stringify(result).slice(0, 300)}`);
}
if (!userInfo.apiKey || userInfo.apiKey.trim() === "") {
throw new Error("iFlow account has no API key provisioned — generate one in the iFlow console");
} Defensive patterns
Strategy: validation
Validate before calling
// validate the user-info payload before/after postExchange
function hasUsableApiKey(data) {
return typeof data === 'object' && data !== null
&& typeof data.apiKey === 'string'
&& data.apiKey.trim().length > 0;
}
// usage: if (!hasUsableApiKey(userInfo)) throw new Error('iFlow API key not provisioned'); Type guard
function isUserInfoWithApiKey(u) {
return typeof u === 'object' && u !== null && 'apiKey' in u
&& typeof u.apiKey === 'string' && u.apiKey.trim() !== '';
} Try / catch
try {
const { userInfo } = await provider.postExchange(tokens);
} catch (e) {
if (e.message === 'Empty API key returned from iFlow') {
// actionable, user-facing: not retryable, direct to iFlow console
return { ok: false, reason: 'no-api-key', hint: 'Generate an API key in the iFlow console, then retry login' };
}
throw e;
} Prevention
- Confirm API-key provisioning as part of account onboarding before wiring up OAuth login.
- If postExchange ever starts throwing this for all accounts, suspect schema drift in result.data — log the raw payload.
- Do not store the mapped account when apiKey is empty; a credential without a key will fail on first API call anyway.
- Add a fixture-based unit test asserting a valid userInfo shape includes apiKey.
When it happens
Trigger: postExchange validates userInfo = result.data || {} and throws when !userInfo.apiKey || userInfo.apiKey.trim() === '' — i.e. data is absent entirely (schema drift), or the account has no API key provisioned yet, or iFlow returned apiKey: '' for a newly registered account.
Common situations: Newly created iFlow accounts where the API key has not been generated yet; response schema change (apiKey renamed/moved out of data) so the check reads undefined; regional restrictions where iFlow declines to issue keys; result.data accidentally null so userInfo defaults to {}.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
- "Missing account email/phone in user info"
- API key is required
- API key validation failed: ${error.message}
- ${provider} API key required
- Missing Zed callback URL
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/989e0f0fdd246162.
Report an issue: GitHub.