jackwener/OpenCLI · error · CommandExecutionError
HTTP ${userLookup.error}: Failed to resolve Twitter user @${
Error message
HTTP ${userLookup.error}: Failed to resolve Twitter user @${targetUser} What it means
CommandExecutionError thrown when the UserByScreenName lookup fails with an HTTP status other than 401/403 (which are handled as auth errors). The message embeds the actual status code and the target screen name, indicating the request to resolve the user's numeric rest_id failed for a non-auth reason.
Source
Thrown at clis/twitter/following.js:201
const headers = {
'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 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));View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the screen name is correct and well-formed (e.g. @elonmusk, no spaces)
- Check the HTTP code in the message: 429 means rate limited — wait and retry; 400/404 means the user or query is invalid
- Update opencli to refresh Twitter query IDs via resolveTwitterQueryId
- Retry later if the code is 5xx (Twitter-side outage)
Example fix
// before: bad screen name -> HTTP 400 $ opencli twitter following '@elon musk' Error: HTTP 400: Failed to resolve Twitter user @@elon musk // after $ opencli twitter following @elonmusk
Defensive patterns
Strategy: try-catch
Validate before calling
function validateHandle(user) {
const m = /^@?([A-Za-z0-9_]{1,15})$/.exec((user || '').trim());
if (!m) throw new Error(`Invalid Twitter handle: ${user}`);
return m[1];
} Type guard
function isTransientHttpStatus(err) {
const m = /HTTP (\d{3})/.exec(String(err && err.message));
return !!m && (m[1].startsWith('5') || m[1] === '429');
} Try / catch
try {
await cli.following(target);
} catch (err) {
const code = (/(\d{3})/.exec(err.message) || [])[1];
if (code === '429') { await sleep(60000); return retry(target); }
if (code && code[0] === '5') { await sleep(5000); return retry(target, 2); }
throw err; // 400/404: bad handle or stale query ID — update CLI
} Prevention
- Validate the screen name format before calling
- Treat 429 as rate limiting: back off exponentially
- Keep opencli updated so resolveTwitterQueryId uses current query IDs
- Retry 5xx errors after a short delay
When it happens
Trigger: The in-page fetch of buildUserByScreenNameQueryUrl(userByScreenNameQueryId, targetUser) returns a status like 400, 404, 429, or 5xx; userLookup.error is truthy but not 401/403, so describe falls to this generic CommandExecutionError.
Common situations: Passing a malformed or nonexistent screen name (400/404); rate limiting after many rapid commands (429); stale hardcoded FOLLOWING/USER_BY_SCREEN_NAME query IDs producing 400; Twitter server-side 5xx incidents.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Following
- autohome ${contextHint} HTTP ${resp.status}
- Chess.com callback returned HTTP ${resp.status} for ${url}
- Ctrip flight API returned HTTP ${status || 'unknown'}
- dongchedi ${contextHint} HTTP ${resp.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8250c13c73790e8e.
Report an issue: GitHub.