jackwener/OpenCLI · error · CommandExecutionError
Failed to add @${username} to list ${listId}: HTTP ${addResu
Error message
Failed to add @${username} to list ${listId}: HTTP ${addResult?.status ?? 0}${addResult?.fetchError ? ' (' + addResult.fetchError + ')' : ''}${addResult?.raw ? ' — ' + addResult.raw : ''} What it means
A CommandExecutionError from buildListAddMemberRow in `clis/twitter/list-add-core.js` thrown when the HTTP layer of the X list-add mutation did not succeed (addResult.httpOk is false). The message embeds the HTTP status (0 when unknown) plus any fetchError or raw body text captured for diagnosis.
Source
Thrown at clis/twitter/list-add-core.js:56
standardized_nudges_misinfo: true,
tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
longform_notetweets_rich_text_read_enabled: true,
longform_notetweets_inline_media_enabled: true,
responsive_web_grok_image_annotation_enabled: true,
responsive_web_enhance_cards_enabled: false,
};
function fatalGraphqlErrors(errors) {
const list = Array.isArray(errors) ? errors : [];
return list.filter((e) =>
!(e?.path || []).join('.').includes('default_banner_media_results')
&& !/decode/i.test(e?.message || '')
);
}
export function buildListAddMemberRow({ addResult, memberCountBefore, listId, username, userId }) {
if (!addResult?.httpOk) {
throw new CommandExecutionError(
`Failed to add @${username} to list ${listId}: HTTP ${addResult?.status ?? 0}${addResult?.fetchError ? ' (' + addResult.fetchError + ')' : ''}${addResult?.raw ? ' — ' + addResult.raw : ''}`
);
}
// X often returns a partial GraphQL error on `default_banner_media_results`
// even on successful mutations. Treat only missing main data or non-decode
// GraphQL errors as command failures.
const hasMemberCount = addResult.mc !== null && addResult.mc !== undefined;
const fatalErrors = fatalGraphqlErrors(addResult.errors);
if (!hasMemberCount && fatalErrors.length) {
const msg = fatalErrors.map((e) => e.message || JSON.stringify(e)).join('; ');
throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: ${msg.slice(0, 300)}`);
}
if (!hasMemberCount) {
throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: no member_count in response`);
}
const memberCountAfter = Number(addResult.mc);View on GitHub (pinned to 49907e53dc)
Solutions
- Refresh your X login cookies and rerun — 401/403 usually means a stale session.
- Check the embedded HTTP status: 429 means back off and retry later; 403 means the account cannot edit this list.
- Verify the listId belongs to the authenticated account (only the list owner can add members).
- Check connectivity/proxy settings if status is 0 with a fetchError.
Example fix
// before: stale cookies produce HTTP 403
await listAddUser(page, { listId: '123456789', username: 'alice' });
// after: refresh session cookies first, then retry
await refreshSessionCookies(page);
await listAddUser(page, { listId: '123456789', username: 'alice' }); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify session and ownership before mutating
const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some(c => c.name === 'auth_token')) throw new Error('No X auth cookies; refresh session first'); Type guard
function isHttpOkAddResult(r) {
return Boolean(r && typeof r === 'object' && r.httpOk === true);
} Try / catch
try {
await listAddUser(page, { listId, username });
} catch (e) {
const m = /HTTP (\d+)/.exec(e.message);
const status = m && Number(m[1]);
if (status === 429) await sleep(15 * 60_000); // rate limited: back off
else if (status === 401 || status === 403) await refreshSessionCookies(page);
else if (status === 0) await checkConnectivity();
throw e;
} Prevention
- Refresh X cookies regularly; expired sessions produce non-2xx statuses.
- Respect rate limits: pace list mutations and back off on 429.
- Confirm the authenticated account owns the target list.
- Log the raw response embedded in the error to diagnose quickly.
When it happens
Trigger: Calling listAddUser/row where the underlying GraphQL add-member request returns a non-2xx status (e.g. 401/403 auth failure, 429 rate limit) or the fetch itself fails (status 0 with a fetchError).
Common situations: Expired X session cookies; account flagged or lacking permission to edit the list; rate limiting after many mutations; network errors / DNS failures before a response arrives.
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
- message (describeTwitterApiError('TweetResultByRestId', rawR
- Could not fetch lists: ${listsData.__error}
- 12306 queryByTrainNo returned HTTP ${resp.status}
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e9c1a31d590b2a6e.
Report an issue: GitHub.