jackwener/OpenCLI · warning · EmptyResultError
twitter profile
Error message
twitter profile
What it means
EmptyResultError('twitter profile') thrown when rawResult.notFound is set — the UserByScreenName response indicated the screen name does not resolve to a user (Twitter returns success with data.user.result absent). It is the typed 'no such entity' outcome, distinct from auth or transport failures.
Source
Thrown at clis/twitter/profile.js:181
if (!result) return {ok: false, notFound: true, error: 'User @' + screenName + ' not found'};
return {ok: true, result};
}
`));
if (!isPlainObject(rawResult)) {
throw new CommandExecutionError('Twitter profile response payload is malformed');
}
if (!rawResult.ok) {
// For HTTP errors, use fork's rich code mapping (429/401/403/404/5xx differentiation
// from describeTwitterApiError); fall back to the plain message for non-HTTP failures
// (fetch threw, JSON parse failed, payload malformed).
const message = typeof rawResult.httpStatus === 'number'
? describeTwitterApiError('UserByScreenName', rawResult.httpStatus, rawResult.hint)
: rawResult.error + (rawResult.hint ? ` (${rawResult.hint})` : '');
if (rawResult.auth) {
throw new AuthRequiredError('x.com', message);
}
if (rawResult.notFound) {
throw new EmptyResultError('twitter profile', message);
}
throw new CommandExecutionError(message);
}
return mapTwitterProfileResult(rawResult.result, username);
}
});
export const __test__ = { mapTwitterProfileResult };
View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the screen name spelling and that the account still exists by opening https://x.com/<username>
- Treat EmptyResultError as 'user not found' in your pipeline and skip the record instead of retrying
- Re-fetch the current handle from your source of truth if the account may have been renamed
- Check whether the profile is suspended/private; those cannot be fetched without following/access
Example fix
// before
const profile = await cli.run('twitter profile', { username: handle });
// after
try {
const profile = await cli.run('twitter profile', { username: handle });
} catch (e) {
if (e instanceof EmptyResultError) return skip(handle); // user does not exist
throw e;
} Defensive patterns
Strategy: try-catch
Type guard
function isEmptyResultError(e) {
return e instanceof EmptyResultError || e.name === 'EmptyResultError';
} Try / catch
try {
return await cli.run('twitter profile', { username });
} catch (e) {
if (e instanceof EmptyResultError) return null; // user does not exist
throw e;
} Prevention
- Normalize handles (strip @, trim whitespace, lowercase check) before lookup
- Maintain a not-found cache to avoid re-querying dead handles
- Periodically re-validate handle lists against renames/suspensions
- Treat not-found as data, not as a retryable fault
When it happens
Trigger: Querying @username that does not exist, was renamed, or is suspended/protected so the GraphQL response has no user.result, making the in-page script return {ok:false, notFound:true}.
Common situations: Typo in the handle; account deleted or renamed since data was collected; querying suspended/banned accounts; region or age-gated profiles; scraping stale handle lists.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Could not find user @${targetUser}
- NOT_FOUND
- NOT_FOUND
- bilibili creator-stats ${bvid}
- bilibili user search: ${input}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/006449318832b19d.
Report an issue: GitHub.