jackwener/OpenCLI · error · CommandExecutionError

Gmail ${operation} requires browser response interception

Error message

Gmail ${operation} requires browser response interception

What it means

installGmailCapture requires the page object to expose startNetworkCapture and readNetworkCapture methods. If either is missing it throws this CommandExecutionError, because Gmail results are read from intercepted /sync network responses, which is impossible without browser response interception support. This is a capability check on the browser-driver wrapper, not a transient fault.

Source

Thrown at clis/gmail/utils.js:294

async function ensureGmailReady(page, account, operation) {
  const currentUrl = typeof page.getCurrentUrl === 'function' ? await page.getCurrentUrl() : null;
  if (!currentUrl?.startsWith(`${GMAIL_ORIGIN}/mail/u/${account}/`)) {
    await page.goto(`${GMAIL_ORIGIN}/mail/u/${account}/#inbox`);
  }
  for (let attempt = 0; attempt < 60; attempt += 1) {
    const ready = unwrapBrowserResult(await page.evaluate(`() => !!document.querySelector('input[name="q"]')`), `${operation} readiness probe`);
    if (ready === true) return;
    await page.sleep(0.5);
  }
  throw new TimeoutError(`Gmail ${operation} page`, 30, 'The Gmail search surface did not become ready. Reload Gmail in the browser and retry.');
}

async function installGmailCapture(page, account, endpoint, operation) {
  if (
    typeof page?.startNetworkCapture !== 'function'
    || typeof page?.readNetworkCapture !== 'function'
  ) {
    throw new CommandExecutionError(`Gmail ${operation} requires browser response interception`);
  }
  if (!await page.startNetworkCapture(`/sync/u/${account}/i/${endpoint}`)) {
    throw new CommandExecutionError(`Gmail ${operation} could not start browser response interception`);
  }
  await page.readNetworkCapture();
}

async function waitGmailCaptures(page, endpoint, operation, timeoutSeconds = CAPTURE_WAIT_SECONDS) {
  const deadline = Date.now() + timeoutSeconds * 1000;
  let bodylessCaptureObserved = false;
  // The bridge capture queue is request-oriented: reading it while a response
  // is still in flight drains that request before its status/body arrive.
  // Give Gmail's own action time to settle before the first read.
  await page.sleep(endpoint === 'fd' ? 1 : 3);
  while (Date.now() < deadline) {
    const entries = await page.readNetworkCapture();
    const endpointEntries = (Array.isArray(entries) ? entries : [])
      .filter((entry) => String(entry?.url || '').includes(`/i/${endpoint}`));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use the library's own browser page wrapper that implements startNetworkCapture/readNetworkCapture
  2. Check typeof page.startNetworkCapture === 'function' before calling Gmail operations
  3. Upgrade/align the browser helper module and the Gmail CLI to compatible versions
  4. If using Puppeteer directly, wrap the page with the library's network-capture instrumentation

Example fix

// before: raw puppeteer page lacks capture API
const page = await browser.newPage();
await listLabels(page, 0);
// after: obtain the instrumented page from the library's helper
const page = await gmailBrowser.open({ capture: true });
await listLabels(page, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof page?.startNetworkCapture !== 'function' || typeof page?.readNetworkCapture !== 'function') {
  throw new Error('page wrapper must implement startNetworkCapture/readNetworkCapture before Gmail operations');
}

Type guard

function hasNetworkCapture(page) {
  return typeof page?.startNetworkCapture === 'function'
    && typeof page?.readNetworkCapture === 'function';
}

Try / catch

try {
  await listLabels(page, 0);
} catch (e) {
  if (/requires browser response interception/.test(e.message)) {
    console.error('Wrong page wrapper; use the library\'s instrumented page');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling queryThreads, listLabels, or fetchThread with a page object whose wrapper does not implement startNetworkCapture or readNetworkCapture (e.g. a plain Puppeteer Page, a custom/driverless page shim, or an older browser-helper version).

Common situations: Passing a vanilla puppeteer page instead of the library's instrumented page wrapper; upgrading the browser helper and losing the capture API; mixing versions of the CLI and its browser module; stub page objects in scripts/tests.

Related errors


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