jackwener/OpenCLI · error · CommandExecutionError
Could not find user @${username}
Error message
Could not find user @${username} What it means
CommandExecutionError thrown when the UserByScreenName GraphQL lookup returns no user rest_id for the requested handle. The library resolves the handle to a numeric user ID before querying Likes; a missing rest_id means the account does not exist, is suspended, or is not resolvable with the current session.
Source
Thrown at clis/twitter/likes.js:269
const likesQueryId = await resolveTwitterQueryId(page, 'Likes', LIKES_QUERY_ID);
const userByScreenNameQueryId = await resolveTwitterQueryId(page, 'UserByScreenName', USER_BY_SCREEN_NAME_QUERY_ID);
const headers = JSON.stringify({
'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
'X-Csrf-Token': ct0,
'X-Twitter-Auth-Type': 'OAuth2Session',
'X-Twitter-Active-User': 'yes',
});
// Get userId from screen_name
const userId = unwrapBrowserResult(await page.evaluate(`async () => {
const screenName = ${JSON.stringify(username)};
const url = ${JSON.stringify(buildUserByScreenNameQueryUrl(userByScreenNameQueryId, username))};
const resp = await fetch(url, { headers: ${headers}, credentials: 'include' });
if (!resp.ok) return null;
const d = await resp.json();
return d.data?.user?.result?.rest_id || null;
}`));
if (!userId) {
throw new CommandExecutionError(`Could not find user @${username}`);
}
const resumed = fetchAll ? readResumeFile(resumeFile, {
source: 'likes',
username,
outputFile: useOutputFile ? outputFile : null,
}) : null;
if (useOutputFile && resumed && resumed.count > 0 && !fs.existsSync(outputFile)) {
throw new CommandExecutionError(`Twitter likes output file is missing for resume state: ${outputFile}`);
}
if (useOutputFile && !resumed && fs.existsSync(outputFile)) {
throw new ArgumentError(`Refusing to overwrite existing Twitter likes output file: ${outputFile}`);
}
const allTweets = useOutputFile ? [] : (resumed?.tweets ? [...resumed.tweets] : []);
const jsonlState = useOutputFile ? loadJsonlArchiveState(outputFile) : null;
const seen = useOutputFile
? jsonlState.seen
: new Set(allTweets.map((tweet) => tweet?.id).filter(Boolean));
if (useOutputFile && resumed && jsonlState.count !== resumed.count) {View on GitHub (pinned to 49907e53dc)
Solutions
- Check the @username for typos and confirm the account exists by opening https://x.com/<username>.
- If the account was renamed, use the current handle.
- Re-authenticate: a stale session can make the lookup return an empty user result.
- If the account is suspended or deactivated, the error is expected; no fix exists.
Example fix
// before $ cli twitter likes @joohn_doe // after $ cli twitter likes @john_doe // corrected handle
Defensive patterns
Strategy: validation
Validate before calling
const handle = username.replace(/^@/, '');
if (!/^[A-Za-z0-9_]{1,15}$/.test(handle)) {
throw new Error(`Invalid Twitter handle: ${username}`);
} Type guard
function isValidHandle(u) { return typeof u === 'string' && /^@?[A-Za-z0-9_]{1,15}$/.test(u); } Try / catch
try {
await cli.twitter.likes({ username });
} catch (e) {
if (/Could not find user @/.test(e.message)) {
console.error(`Handle '${username}' not found; verify it exists at https://x.com/${username.replace('@','')}`);
} else throw e;
} Prevention
- Verify the handle resolves on x.com before scripting it
- Strip stray characters like @ or whitespace from CLI args
- Handle renames by storing user IDs, not just handles
- Treat suspended/deactivated accounts as expected failures
When it happens
Trigger: fetchUserByScreenName (in-page fetch of the UserByScreenName GraphQL endpoint) returns resp.ok but d.data.user.result.rest_id is falsy, so clis/twitter/likes.js:269 throws `Could not find user @${username}`.
Common situations: Typo in the @username passed on the command line; the account was renamed or deleted; the account is suspended/locked; running against a handle whose visibility changed (protected/deactivated).
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- Homebrew API returned 404 for ${url}.
- Lichess returned 404 for ${url}.
- REST Countries returned 404 for ${url}.
- NOT_FOUND
- message (describeTwitterApiError('TweetResultByRestId', rawR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e5f5a60a95f618c0.
Report an issue: GitHub.