jackwener/OpenCLI · error · ArgumentError
Invalid Twitter/X username: ${JSON.stringify(part.trim())}
Error message
Invalid Twitter/X username: ${JSON.stringify(part.trim())} What it means
parseBatchUsernames validates each comma-separated token against USERNAME_RE after stripping leading '@' characters and throws ArgumentError for any token that does not match. Twitter/X screen names allow only alphanumerics and underscores, so spaces, hyphens, dots, slashes, or URLs fail validation. The JSON.stringify of the raw token in the message identifies the offending part.
Source
Thrown at clis/twitter/follow-batch.js:21
import { unwrapBrowserResult } from './shared.js';
const USERNAME_RE = /^[A-Za-z0-9_]{1,15}$/;
const DEFAULT_DELAY_MS = 3000;
const MAX_DELAY_MS = 60000;
export function parseBatchUsernames(input) {
const raw = String(input || '').trim();
if (!raw) {
throw new ArgumentError('At least one Twitter/X username is required');
}
const usernames = [];
const seen = new Set();
for (const part of raw.split(',')) {
const username = part.trim().replace(/^@+/, '');
if (!username) continue;
if (!USERNAME_RE.test(username)) {
throw new ArgumentError(`Invalid Twitter/X username: ${JSON.stringify(part.trim())}`);
}
const key = username.toLowerCase();
if (seen.has(key)) continue;
seen.add(key);
usernames.push(username);
}
if (!usernames.length) {
throw new ArgumentError('At least one Twitter/X username is required');
}
return usernames;
}
async function readFollowState(page, username) {
return unwrapBrowserResult(await page.evaluate(`(async () => {
try {
let attempts = 0;
while (attempts < 20) {View on GitHub (pinned to 49907e53dc)
Solutions
- Replace each item with the bare screen name (letters, digits, underscore only): '@alice,@bob_99', not 'https://x.com/alice'.
- Strip URLs/prefixes before invoking, e.g. sed 's#https://x.com/##g'.
- Check the input source for invisible characters (CRLF, quotes); trim and normalize line endings.
- Fix only the token named in the message — tokens that reduce to empty after '@'-stripping are skipped, not errors.
Example fix
// before opencli twitter follow-batch 'https://x.com/alice,@bob-1' // after opencli twitter follow-batch 'alice,bob_1'
Defensive patterns
Strategy: validation
Validate before calling
const USERNAME_RE = /^[A-Za-z0-9_]{1,15}$/;
function sanitizeUsernames(input) {
return String(input ?? '')
.split(',')
.map((p) => p.trim().replace(/^@+/, ''))
.filter((u) => u && !USERNAME_RE.test(u) ? (console.error(`Skipping invalid: ${u}`), false) : Boolean(u));
}
// Pre-strip URLs: input.replaceAll(/https?:\/\/x\.com\//g, '') Type guard
function isValidUsername(u) {
return typeof u === 'string' && /^[A-Za-z0-9_]{1,15}$/.test(u);
} Try / catch
try {
await followBatch(rawUsernames);
} catch (e) {
if (e.code === 'ARGUMENT' && e.message.startsWith('Invalid Twitter/X username')) {
const bad = e.message.match(/"(.*)"/)?.[1];
console.error(`Remove or fix the invalid token: ${bad}`);
} else throw e;
} Prevention
- Strip profile URLs to screen names before passing them in.
- Normalize input: trim, remove quotes, fix CRLF line endings from Windows sources.
- Pre-validate each token with /^[A-Za-z0-9_]{1,15}$/ in your pipeline.
- Keep names bare — no '@' needed (stripped anyway), no hyphens/dots (not allowed on X).
When it happens
Trigger: Passing a full profile URL (https://x.com/alice) instead of the screen name; tokens with hyphens/dots; stray quotes or punctuation around names; tokens with embedded spaces or invisible characters (CRLF) that break the regex.
Common situations: Copy-pasting profile URLs into the username list; piping usernames from another tool with trailing punctuation; Windows line endings adding hidden \r characters; typos like 'bo b'.
Related errors
- Invalid listId: ${JSON.stringify(kwargs.listId)}. Expected n
- twitter list-add username is required
- twitter tweets --limit must be an integer between 1 and ${MA
- twitter tweets --page-delay must be an integer between 0 and
- ${label} must be a non-negative integer, got ${JSON.stringif
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5558c14b71ccd8ce.
Report an issue: GitHub.