jackwener/OpenCLI · error · CommandExecutionError

Browser session required for twitter post

Error message

Browser session required for twitter post

What it means

The twitter post command's func requires an active browser page object; if `page` is falsy (no browser session was started before invoking the CLI), it throws this CommandExecutionError immediately, before any browser interaction. The library cannot post a tweet without a live browser session, so it fails fast with this explicit message.

Source

Thrown at clis/twitter/post.js:306

    return result;
}

cli({
    site: 'twitter',
    name: 'post',
    access: 'write',
    description: 'Post a new tweet/thread',
    domain: 'x.com',
    strategy: Strategy.UI,
    browser: true,
    args: [
        { name: 'text', type: 'string', required: true, positional: true, help: 'The text content of the tweet' },
        { name: 'images', type: 'string', required: false, help: 'Image paths, comma-separated, max 4 (jpg/png/gif/webp)' },
    ],
    columns: ['status', 'message', 'text', 'id', 'url'],
    func: async (page, kwargs) => {
        if (!page)
            throw new CommandExecutionError('Browser session required for twitter post');

        // Validate images upfront before any browser interaction.
        const absPaths = kwargs.images ? validateImagePaths(String(kwargs.images)) : [];
        const text = String(kwargs.text ?? '');

        // The current X standalone composer is /compose/post. It keeps a single,
        // visible composer and is the same route used by the reply command.
        await page.goto(COMPOSE_URL, { waitUntil: 'load', settleMs: 2500 });
        await page.wait({ selector: '[data-testid="tweetTextarea_0"]', timeout: 15 });

        // Attach media before inserting text. Uploading media after Draft.js has
        // text can re-render/reset the editor, causing image-only posts.
        if (absPaths.length > 0) {
            await page.wait({ selector: FILE_INPUT_SELECTOR, timeout: 20 });
            if (page.setFileInput) {
                try {
                    await page.setFileInput(absPaths, FILE_INPUT_SELECTOR);
                } catch (err) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Start/connect the browser session (the CLI's browser open/start command) before running `twitter post`
  2. Reopen the session if the browser crashed or was closed mid-run, then retry the post
  3. In scripted use, assert the page handle exists before invoking the command func

Example fix

// before
await cli.run('twitter post', { text: 'hello' });
// after: ensure a session exists first
const page = await cli.run('browser open', { url: 'https://x.com' });
if (!page) throw new Error('browser session unavailable');
await cli.run('twitter post', { text: 'hello' });
Defensive patterns

Strategy: validation

Validate before calling

if (!page) throw new Error('Open a browser session (browser open/start) before running twitter post');

Type guard

function hasBrowserSession(page) { return page != null && typeof page.evaluate === 'function' && !page.isClosed?.(); }

Try / catch

try {
  await cli.run('twitter post', { text });
} catch (e) {
  if (String(e.message).includes('Browser session required')) { await cli.run('browser open', { url: 'https://x.com' }); return cli.run('twitter post', { text }); }
  throw e;
}

Prevention

When it happens

Trigger: Calling the `twitter post` command without first launching/connecting the browser session (e.g. skipping the browser-open/start command, or invoking the CLI's func directly with page = null/undefined).

Common situations: Running the post command in a fresh CLI process without opening the browser first; automation scripts calling the command's func out of order; a crashed or closed browser leaving the session handle null; forgetting the session flag/URL in a batch runner.

Related errors


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