jackwener/OpenCLI · error · CommandExecutionError
Could not find user @${targetUser}
Error message
Could not find user @${targetUser} What it means
CommandExecutionError thrown when the UserByScreenName lookup succeeds (HTTP 200) but the response contains no user rest_id — d.data?.user?.result?.rest_id is null/undefined. This means Twitter did not return an account for the given screen name.
Source
Thrown at clis/twitter/following.js:205
'X-Twitter-Active-User': 'yes',
};
// Get userId from screen_name
const userLookup = unwrapBrowserResult(await page.evaluate(async (url, headers) => {
const resp = await fetch(url, { headers, credentials: 'include' });
if (!resp.ok) return { error: resp.status };
const d = await resp.json();
return { userId: d.data?.user?.result?.rest_id || null };
}, buildUserByScreenNameQueryUrl(userByScreenNameQueryId, targetUser), headers));
if (userLookup?.error === 401 || userLookup?.error === 403) {
throw new AuthRequiredError('x.com', `Twitter user lookup failed (HTTP ${userLookup.error})`);
}
if (userLookup?.error) {
throw new CommandExecutionError(`HTTP ${userLookup.error}: Failed to resolve Twitter user @${targetUser}`);
}
const userId = userLookup?.userId || null;
if (!userId)
throw new CommandExecutionError(`Could not find user @${targetUser}`);
const allUsers = [];
const seen = new Set();
let cursor = null;
let lastRawResponse = null;
// Runaway guard only; --limit and cursor exhaustion control normal pagination.
for (let i = 0; i < MAX_PAGINATION_PAGES && allUsers.length < limit; i++) {
const fetchCount = Math.min(50, limit - allUsers.length + 10);
const apiUrl = buildFollowingUrl(followingQueryId, userId, fetchCount, cursor);
const data = unwrapBrowserResult(await page.evaluate(async (url, headers) => {
const r = await fetch(url, { headers, credentials: 'include' });
return r.ok ? await r.json() : { error: r.status };
}, apiUrl, headers));
if (data?.error) {
if (data.error === 401 || data.error === 403)
throw new AuthRequiredError('x.com', `Twitter following request failed (HTTP ${data.error})`);
throw new CommandExecutionError(describeTwitterApiError('Following', data.error));View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the handle exists by opening https://x.com/<name> in a browser
- Check for typos or recent renames of the account
- Retry after updating opencli if Twitter changed the response shape (rest_id path)
- Use the numeric user ID directly if the CLI supports it, bypassing the screen-name lookup
Example fix
// before: nonexistent handle $ opencli twitter following @thisuserdoesnotexist12345 Error: Could not find user @thisuserdoesnotexist12345 // after: use a real, existing handle $ opencli twitter following @elonmusk
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check that the handle exists before running the following command
const { execSync } = require('child_process');
const status = execSync(`curl -s -o /dev/null -w '%{http_code}' https://x.com/${handle.replace('@','')}`).trim();
if (status !== '200') throw new Error(`@${handle.replace('@','')} does not exist or is unavailable`); Type guard
function lookupSucceeded(d) {
return d && typeof d === 'object' && typeof d?.data?.user?.result?.rest_id === 'string' && d.data.user.result.rest_id.length > 0;
} Try / catch
try {
await cli.following(target);
} catch (err) {
if (/Could not find user @/.test(err.message)) {
console.error('Check the handle at https://x.com/' + target.replace('@','') + ' — it may be renamed, deleted, or suspended.');
} else throw err;
} Prevention
- Verify the handle exists on x.com before scripting against it
- Watch for renamed/deleted/suspended accounts in tracked lists
- Handle Twitter response-shape changes by keeping the CLI updated
- Prefer numeric user IDs when available to avoid screen-name drift
When it happens
Trigger: After a non-error API response, userId is falsy: the screen name does not exist, was renamed, or the account is suspended/removed, so the nested rest_id path resolves to null.
Common situations: Typo in the handle; the account was deleted, renamed, or suspended; requesting a protected/withheld account from a region where it is unavailable; Twitter changing the UserByScreenName response shape after an API update so rest_id sits at a different path.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Could not find user @${username}
- Could not resolve user @${username}
- List ${listId} not found among your lists (${listsBefore.len
- Could not resolve user @${username}
- twitter profile
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a4fe5a720b6583a1.
Report an issue: GitHub.