jackwener/OpenCLI · warning · EmptyResultError

gmail search

gmail search

Error message

No threads matched "${normalizedQuery}"

What it means

EmptyResultError with code 'gmail search' thrown when a search completed successfully but matched zero threads. The library treats 'no results' as a distinct, expected condition so callers can handle it separately from real failures.

Source

Thrown at clis/gmail/utils.js:542

      'bv',
      pageNumber === 1 ? 'thread list' : `thread pagination page ${pageNumber}`,
    );
    const pageRows = bodies.flatMap(parseBatchView);
    let added = 0;
    for (const row of pageRows) {
      if (seen.has(row.threadId)) continue;
      seen.add(row.threadId);
      rows.push(row);
      added += 1;
      if (rows.length >= limit) return rows;
    }
    if (pageNumber > 1 && added === 0) {
      throw new CommandExecutionError(`Gmail thread pagination page ${pageNumber} repeated an earlier response; refusing partial results`);
    }
    if (pageRows.length < PAGE_SIZE) break;
  }
  if (rows.length === 0) {
    throw new EmptyResultError('gmail search', `No threads matched "${normalizedQuery}"`);
  }
  return rows.slice(0, limit);
}

export async function listLabels(page, account = 0) {
  await ensureGmailReady(page, account, 'labels');
  await installGmailCapture(page, account, 'bv', 'labels');
  await submitSearch(page, 'in:anywhere', 'labels');
  const bodies = await waitGmailCaptures(page, 'bv', 'labels');
  const labels = bodies.flatMap(parseLabels);
  const fallback = labels.length === 0 ? await renderedLabels(page, account) : [];
  const unique = [...new Map([...labels, ...fallback].map((row) => [row.id, row])).values()];
  if (unique.length === 0) throw new EmptyResultError('gmail labels', 'Gmail returned no labels');
  return unique;
}

export function legacyThreadId(value) {
  const raw = cleanString(value);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Broaden the query (remove filters, widen the date range)
  2. Verify the label/address in the query exists in the target account
  3. Catch EmptyResultError and treat it as a valid empty outcome
  4. Check you are on the expected account index (account option)

Example fix

// before
const rows = await queryThreads(page, 'from:ghost@nowhere.test');
// after
try {
  const rows = await queryThreads(page, 'from:ghost@nowhere.test');
} catch (e) {
  if (e instanceof EmptyResultError) return [];
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try { rows = await queryThreads(page, q); }
catch (e) { if (e instanceof EmptyResultError && e.code === 'gmail search') return []; throw e; }

Prevention

When it happens

Trigger: queryThreads(page, query) where the query matches no mail: overly narrow filters, wrong label names, mail in an account that has none, misspelled Gmail operators.

Common situations: Searching a secondary/test account that has no mail; using operators like label:foo where the label doesn't exist; date filters (older_than/newer_than) excluding everything.

Related errors


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