jackwener/OpenCLI · error · CommandExecutionError

Browser session required for twitter block

Error message

Browser session required for twitter block

What it means

The twitter block command's func requires an interactive browser page; when page is null it throws CommandExecutionError('Browser session required for twitter block'). Blocking is performed by driving the real x.com UI (menus, confirm dialog), so it cannot run without an active browser session.

Source

Thrown at clis/twitter/block.js:17

import { CommandExecutionError, TimeoutError } from '@jackwener/opencli/errors';
import { cli, Strategy } from '@jackwener/opencli/registry';
cli({
    site: 'twitter',
    name: 'block',
    access: 'write',
    description: 'Block a Twitter user',
    domain: 'x.com',
    strategy: Strategy.UI,
    browser: true,
    args: [
        { name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (without @)' },
    ],
    columns: ['status', 'message'],
    func: async (page, kwargs) => {
        if (!page)
            throw new CommandExecutionError('Browser session required for twitter block');
        const username = kwargs.username.replace(/^@/, '');
        await page.goto(`https://x.com/${username}`);
        await page.wait({ selector: '[data-testid="primaryColumn"]' });
        const result = await page.evaluate(`(async () => {
        let writeStarted = false;
        try {
            let attempts = 0;
            const getPrimary = () => document.querySelector('[data-testid="primaryColumn"]');
            const isBlockMenuItem = (item) => {
                const text = String(item.textContent || '');
                const lower = text.toLowerCase();
                const isUnblockText = lower.includes('unblock') || text.includes('取消屏蔽') || text.includes('解除屏蔽');
                const isBlockText = (lower.includes('block') || text.includes('屏蔽')) && !isUnblockText;
                return item.getAttribute('data-testid') === 'block' || isBlockText;
            };
            if (!getPrimary()) {
                return { ok: false, message: 'Could not find profile surface. Are you logged in?' };
            }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Start/open a browser session (the CLI's browser open command) before running twitter block.
  2. Re-run the command through the normal CLI entrypoint so the page is injected into func.
  3. Ensure the browser hasn't crashed/closed mid-session; restart it if needed.
  4. For headless automation, launch the controlled browser (headless is fine) rather than skipping it.

Example fix

// before
await cli.run('twitter block @user');
// after
await cli.run('browser open');
await cli.run('auth login x.com');
await cli.run('twitter block @user');
Defensive patterns

Strategy: validation

Validate before calling

if (!cli.isBrowserOpen()) {
  await cli.run('browser open');
}
if (!(await hasSessionCookies('x.com'))) {
  await cli.run('auth login x.com');
}

Type guard

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

Try / catch

try {
  await cli.run('twitter block @user');
} catch (e) {
  if (/Browser session required/.test(e.message)) {
    await cli.run('browser open');
    return cli.run('twitter block @user');
  }
  throw e;
}

Prevention

When it happens

Trigger: Invoking the twitter block command in a context where no browser page is bound — e.g. calling the command outside the browser-attached command registry, or the browser session was closed/not started before running the command.

Common situations: Running the command before starting the CLI's browser, after closing the browser window, in CI without a browser, or calling the underlying function directly without page injection.

Related errors


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