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

  1. Log into x.com in the browser session used by the CLI (ensure a fresh ct0 cookie exists)
  2. Re-run the command after re-authenticating
  3. If 403 persists despite a valid session, check the account's status/restrictions on x.com
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/c34a799f0310383b. Report an issue: GitHub.