jackwener/OpenCLI · error · AuthRequiredError
Twitter CreateList returned HTTP ${result.httpStatus}
Error message
Twitter CreateList returned HTTP ${result.httpStatus} What it means
This AuthRequiredError is thrown by requireCreateListResult when Twitter's CreateList GraphQL endpoint responds with HTTP 401 (unauthorized) or 403 (forbidden), meaning the session cookies are missing, expired, or lack permission to create lists. It signals that the user must (re)authenticate with x.com before retrying.
Source
Thrown at clis/twitter/list-create.js:45
}
if (name.length > NAME_MAX) {
throw new ArgumentError(`List name too long: ${name.length} chars (max ${NAME_MAX})`);
}
if (description.length > DESCRIPTION_MAX) {
throw new ArgumentError(`Description too long: ${description.length} chars (max ${DESCRIPTION_MAX})`);
}
if (modeRaw !== 'public' && modeRaw !== 'private') {
throw new ArgumentError(`Invalid mode: ${JSON.stringify(kwargs.mode)}. Expected "public" or "private".`);
}
return { listName: name, listDescription: description, listMode: modeRaw, privateFlag: modeRaw === 'private' };
}
function requireCreateListResult(result, expectedName, expectedMode) {
if (!result || typeof result !== 'object') {
throw new CommandExecutionError(`Unexpected result from twitter list-create: ${JSON.stringify(result)}`);
}
if (result.httpStatus === 401 || result.httpStatus === 403) {
throw new AuthRequiredError('x.com', `Twitter CreateList returned HTTP ${result.httpStatus}`);
}
if (!result.ok) {
const snippet = String(result.bodyText || '').slice(0, 300);
throw new CommandExecutionError(`HTTP ${result.httpStatus} from CreateList: ${snippet}`);
}
if (!result.bodyJson || typeof result.bodyJson !== 'object') {
throw new CommandExecutionError(`CreateList returned malformed JSON payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);
}
const list = result.bodyJson?.data?.list;
if (!list || typeof list !== 'object') {
const errors = result.bodyJson?.errors;
if (Array.isArray(errors) && errors.length > 0) {
throw new CommandExecutionError(`CreateList failed: ${errors[0].message || JSON.stringify(errors[0])}`);
}
throw new CommandExecutionError(`CreateList returned no list payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);
}
const id = String(list.id_str || list.id || '');
if (!/^\d+$/.test(id)) {View on GitHub (pinned to 49907e53dc)
Solutions
- Log into x.com in the browser session used by the CLI (ensure a fresh ct0 cookie exists)
- Re-run the command after re-authenticating
- If 403 persists despite a valid session, check the account's status/restrictions on x.com
- Verify no proxy/extension is stripping cookies from the page context
Example fix
// before // command run with an expired x.com session -> HTTP 401 // after // log into x.com in the automation browser, then: opencli twitter list-create "My List"
Defensive patterns
Strategy: try-catch
Validate before calling
const cookies = await page.getCookies({ url: 'https://x.com' });
const hasCt0 = cookies.some((c) => c.name === 'ct0');
if (!hasCt0) {
throw new Error('Not logged into x.com: authenticate before creating a list');
} Type guard
function isAuthErrorForCreateList(e) {
return e instanceof AuthRequiredError && /CreateList returned HTTP (401|403)/.test(e.message);
} Try / catch
try {
await opencli.twitter.listCreate({ name, description, mode });
} catch (e) {
if (isAuthErrorForCreateList(e)) {
await loginToX(); // re-establish session cookies
return retryListCreate();
}
throw e;
} Prevention
- Check the x.com session/ct0 cookie exists before running write commands
- Periodically refresh the login in the automation browser profile
- Handle AuthRequiredError explicitly in scripts to trigger a re-login flow
- Don't conflate 403 from rate limits with a bad session — retry with backoff only after confirming auth is valid
When it happens
Trigger: Calling `opencli twitter list-create` while not logged into x.com, with an expired session cookie, or with a ct0 cookie that doesn't match the session (CSRF mismatch); account restrictions can also yield 403.
Common situations: Stale browser cookies after a logout/password change; running headless automation without a logged-in profile; Twitter rate-limiting or flagging the account (403); corporate proxies stripping cookies.
Related errors
- Gmail ${operation} returned HTTP ${status}
- 未登录或登录已过期,请先在浏览器中登录贝壳找房
- LinkedIn Learning auth failed (HTTP ${result.status ?? ''}).
- MiniMax ${region.host} rejected ${MINIMAX_API_KEY_VAR} (HTTP
- NotebookLM RPC returned auth error (${errorCode})
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c34a799f0310383b.
Report an issue: GitHub.