jackwener/OpenCLI · error · CommandExecutionError

Browser session required for twitter follow-batch

Error message

Browser session required for twitter follow-batch

What it means

The twitter follow-batch command performs all work through a live browser Page (cookies via page.getCookies, in-page evaluation on x.com), so it throws CommandExecutionError when invoked with no browser session (page is null). The CLI was run without the browser daemon/extension connected, or the command's func was called programmatically without a page.

Source

Thrown at clis/twitter/follow-batch.js:142

    return value;
}

cli({
    site: 'twitter',
    name: 'follow-batch',
    access: 'write',
    description: 'Follow multiple Twitter/X users from a comma-separated username list',
    domain: 'x.com',
    strategy: Strategy.UI,
    browser: true,
    args: [
        { name: 'usernames', type: 'string', positional: true, required: true, help: 'Comma-separated Twitter/X screen names, with or without @' },
        { name: 'delay-ms', type: 'int', default: DEFAULT_DELAY_MS, help: 'Delay between follow attempts in milliseconds' },
    ],
    columns: ['username', 'status', 'message'],
    func: async (page, kwargs) => {
        if (!page) {
            throw new CommandExecutionError('Browser session required for twitter follow-batch');
        }

        const usernames = parseBatchUsernames(kwargs.usernames);
        const delayMs = parseDelayMs(kwargs['delay-ms']);
        const cookies = await page.getCookies({ url: 'https://x.com' });
        const ct0 = cookies.find((cookie) => cookie.name === 'ct0')?.value || null;
        if (!ct0) {
            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
        }

        const rows = [];
        for (const [index, username] of usernames.entries()) {
            if (index > 0 && delayMs > 0) {
                await page.wait(delayMs / 1000);
            }
            rows.push(await followOne(page, username));
        }
        return rows;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Start/connect the browser session first (launch Chrome with the CLI's daemon/extension) and re-run the command.
  2. Verify the daemon is running and the extension is connected before invoking write commands.
  3. In scripts, check that a page/session object exists before calling the command's func.
  4. Route through the normal CLI entrypoint so session setup happens automatically instead of calling func with a null page.

Example fix

// before
await followBatch.func(null, { usernames: 'alice' })
// after
const page = await connectBrowser(); // ensure session
await followBatch.func(page, { usernames: 'alice' })
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the session before invoking the command
async function ensureBrowserSession(getPage) {
  const page = typeof getPage === 'function' ? await getPage() : getPage;
  if (!page) throw new Error('Browser session required: start/connect Chrome before running twitter commands');
  return page;
}

Type guard

function hasPage(page) {
  return page !== null && page !== undefined && typeof page.evaluate === 'function' && typeof page.getCookies === 'function';
}

Try / catch

try {
  await followBatch(usernames);
} catch (e) {
  if (e.code === 'COMMAND_EXEC' && e.message.includes('Browser session required')) {
    await startOrConnectBrowser(); // daemon/extension
    return retry(followBatch, usernames);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `opencli twitter follow-batch ...` with no connected browser session (daemon not running, extension not connected); invoking func(page, kwargs) directly with page = null; the browser session dropped before the command body executed.

Common situations: Forgetting to start the Chrome/Chromium daemon or connect the extension first; running in CI/headless environments with no browser attached; a prior command crashed the session so the next receives no page.

Related errors


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