jackwener/OpenCLI · error · ArgumentError
twitter list-remove username is required
Error message
twitter list-remove username is required
What it means
After validating listId, listRemoveUser normalizes kwargs.username (strips a leading '@') and requires a non-empty result, otherwise throwing ArgumentError 'twitter list-remove username is required' at list-remove-core.js:58. The username is needed both to resolve the user's numeric id via UserByScreenName and to navigate to their profile for the UI removal flow.
Source
Thrown at clis/twitter/list-remove-core.js:58
responsive_web_enhance_cards_enabled: false,
};
export function interpretRemoveResponse(status, json) {
if (status === 200 && json && (json.id_str || json.id || json.slug)) return { ok: true };
if (json && Array.isArray(json.errors) && json.errors.length > 0) {
const err = json.errors[0];
return { ok: false, error: `${err.code ? '[' + err.code + '] ' : ''}${err.message || 'Unknown error'}` };
}
return { ok: false, error: `HTTP ${status}` };
}
export async function listRemoveUser(page, kwargs) {
const listId = String(kwargs.listId || '').trim();
const username = String(kwargs.username || '').replace(/^@/, '').trim();
if (!listId || !/^\d+$/.test(listId)) {
throw new ArgumentError(`Invalid listId: ${JSON.stringify(kwargs.listId)}. Expected numeric ID.`);
}
if (!username) throw new ArgumentError('twitter list-remove username is required');
// Strategy.UI does not get a domain URL pre-nav from the framework.
// This page context is load-bearing for pre-target GraphQL calls below.
await page.goto('https://x.com');
await page.wait(3);
const cookies = await page.getCookies({ url: 'https://x.com' });
const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
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',
});
const userLookupUrl = buildUserByScreenNameQueryUrl(userByScreenNameQueryId, username);View on GitHub (pinned to 49907e53dc)
Solutions
- Supply the screen name: `opencli twitter list-remove <numericListId> alice`
- Quote the '@' form if needed — '@alice' is accepted (the leading @ is stripped) — but ensure it isn't empty
- Check your shell: `opencli ... list-remove "$LIST_ID" "$USER"` and confirm USER isn't unset/empty (set -u helps)
- If calling listRemoveUser directly, pass kwargs = { listId: '123...', username: 'alice' } with both keys present
- Run `opencli twitter list-remove --help` to confirm the expected argument order for your version
Example fix
// before (empty variable)
opencli twitter list-remove 1734567890123456789 "$TARGET_USER" # TARGET_USER unset -> ''
// after
: "${TARGET_USER:?TARGET_USER must be set}"
opencli twitter list-remove 1734567890123456789 "$TARGET_USER" Defensive patterns
Strategy: validation
Validate before calling
function requireUsername(raw) {
const u = String(raw ?? '').replace(/^@/, '').trim();
if (!u) throw new Error('username is required for twitter list-remove');
return u;
}
// call: await removeUser(listId, requireUsername(process.env.TARGET_USER)); Type guard
function hasUsername(kwargs) {
return kwargs != null && typeof kwargs.username === 'string' && kwargs.username.replace(/^@/, '').trim().length > 0;
} Try / catch
try {
await run(`opencli twitter list-remove ${listId} ${username}`);
} catch (e) {
if (e instanceof ArgumentError && /username is required/.test(e.message)) {
// fix argument construction, then retry once
if (!username) throw new Error('Caller bug: username was empty; resolve it before retrying');
return run(`opencli twitter list-remove ${listId} ${username}`);
}
throw e;
} Prevention
- Check argument count/order with --help before scripting
- Use ${VAR:?msg} in shell so empty variables fail early
- Remember a bare '@' still fails — the handle text itself is required
- When calling listRemoveUser directly, assert both kwargs keys exist first
When it happens
Trigger: Invoking the list-remove command without the username argument; passing an empty string or only '@'; kwargs.username being undefined/null when called programmatically; a typo where the second positional argument was swallowed by shell quoting; passing the username in an option slot the CLI doesn't recognize so it never reaches kwargs.username.
Common situations: Forgetting the second positional arg in scripts; shell variables that expand to empty (USERNAME=''); assuming '@handle' alone is rejected when actually only an empty value is — the failure is passing '' or omitting it; CLI arg parsing differences that drop arguments starting with '@' (some tools treat @file specially).
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid listId: ${JSON.stringify(kwargs.listId)}. Expected n
- twitter collection username must be a valid Twitter/X handle
- <train-no> must not be empty
- keyword must not be empty
- <from> station must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/34351d22f05800f5.
Report an issue: GitHub.