jackwener/OpenCLI · error · TimeoutError

Gmail ${operation} capture

Error message

Gmail ${operation} capture

What it means

waitGmailCaptures throws this TimeoutError when no /{endpoint} response was observed at all within timeoutSeconds (default CAPTURE_WAIT_SECONDS) after the Gmail action. The capture never saw a matching /sync request/response, so there is nothing to parse.

Source

Thrown at clis/gmail/utils.js:350

      }
      matches.push(...settledEndpointEntries.filter((entry) => (
        typeof entry?.responsePreview === 'string' || entry?.responseBodyTruncated === true
      )));
      if (bodylessCaptureObserved) {
        throw new CommandExecutionError(
          `Gmail ${operation} capture included a response without a body; refusing possibly partial results`,
        );
      }
      return matches.map((entry) => parseJsonCapture(entry, operation));
    }
    await page.sleep(0.25);
  }
  if (bodylessCaptureObserved) {
    throw new CommandExecutionError(
      `Gmail ${operation} capture lost a response body; refusing possibly partial results`,
    );
  }
  throw new TimeoutError(`Gmail ${operation} capture`, timeoutSeconds, `No /${endpoint} response was observed after the Gmail action.`);
}

async function renderedLabels(page, account) {
  await page.goto(`${GMAIL_ORIGIN}/mail/u/${account}/#settings/labels`);
  await page.sleep(2);
  const rows = unwrapBrowserResult(await page.evaluate(`() => {
    const routes = new RegExp('^(?:#(?:inbox|starred|snoozed|sent|drafts|important|spam|trash)|#label/)');
    const systemNames = {
      inbox: 'Inbox', starred: 'Starred', snoozed: 'Snoozed', sent: 'Sent',
      drafts: 'Drafts', important: 'Important', spam: 'Spam', trash: 'Trash',
      scheduled: 'Scheduled', all: 'All Mail',
      'category/purchases': 'Purchases', 'category/social': 'Social',
      'category/updates': 'Updates', 'category/forums': 'Forums',
      'category/promotions': 'Promotions',
    };
    const seen = new Set();
    const result = [];
    const add = (id, name, type, unreadCount = null) => {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the query; transient timing issues are the most common cause
  2. Confirm the action actually fired (search box contained the query, Enter was pressed) — see the 'requires native browser input' errors otherwise
  3. Increase CAPTURE_WAIT_SECONDS for slow networks
  4. Check whether Gmail's UI/update changed the /sync/i/{endpoint} URL pattern and update the endpoint constant
  5. Reload Gmail and retry to clear any stale page state
Defensive patterns

Strategy: retry

Validate before calling

// confirm the action fires a sync call before waiting on captures
const q = await page.evaluate('() => document.querySelector("input[name=q]")?.value || ""');
if (!q) throw new Error('search query never set; /sync will not be triggered');

Try / catch

try {
  const threads = await queryThreads(page, 'from:boss@corp.com');
} catch (e) {
  if (e instanceof TimeoutError && /capture/.test(e.message)) {
    await page.sleep(3);
    return queryThreads(page, 'from:boss@corp.com'); // retry with longer capture window
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling queryThreads/fetchThread where after submitSearch (or the action) no /sync/u/N/i/{endpoint} entry appears in page.readNetworkCapture() before the deadline.

Common situations: Gmail served results from cache without a network /sync call; the search submission didn't actually trigger a sync (Enter key not dispatched natively); request URL pattern changed after a Gmail UI update; extremely slow network exceeding the capture timeout.

Related errors


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