jackwener/OpenCLI · error · ArgumentError

thread must be a Gmail thread id from `gmail search` or a Gm

Error message

thread must be a Gmail thread id from `gmail search` or a Gmail thread URL

What it means

legacyThreadId() accepts an id like 'abc123...' (10+ hex chars), a Gmail thread URL ending in a hex id, or a '#thread-f:<decimal>' sync id which it converts to hex. Anything else raises ArgumentError. It enforces that callers pass identifiers obtained from `gmail search` or a thread URL.

Source

Thrown at clis/gmail/utils.js:566

  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);
  const fromUrl = raw.match(/\/(?:[a-f\d]{10,})$/i)?.[0]?.slice(1);
  if (fromUrl) return fromUrl.toLowerCase();
  if (/^[a-f\d]{10,}$/i.test(raw)) return raw.toLowerCase();
  const sync = raw.replace(/^#/, '').match(/^thread-f:(\d+)$/);
  if (sync) return BigInt(sync[1]).toString(16);
  throw new ArgumentError('thread must be a Gmail thread id from `gmail search` or a Gmail thread URL');
}

export async function fetchThread(page, target, account = 0) {
  const legacyId = legacyThreadId(target);
  await ensureGmailReady(page, account, 'thread');
  await installGmailCapture(page, account, 'fd', 'thread');
  const targetState = unwrapBrowserResult(await page.evaluate(`async () => {
    const row = document.querySelector('[data-legacy-thread-id="${legacyId}"]');
    if (!row) return { found: false };
    const clickable = row.querySelector('.y6, .bog, td:nth-child(5)') || row;
    const before = location.href;
    clickable.click();
    await new Promise((resolve) => setTimeout(resolve, 150));
    const rect = clickable.getBoundingClientRect();
    return { found: true, changed: location.href !== before, x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
  }`), 'thread row lookup');
  if (targetState?.found && !targetState.changed && typeof page.nativeClick === 'function') {
    await page.nativeClick(targetState.x, targetState.y);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a thread id exactly as returned by queryThreads/gmail search
  2. Extract the id from the Gmail thread URL path segment before calling
  3. If you have '#thread-f:<n>' sync ids, pass them as-is — they are supported
  4. Log/inspect the value you pass; ensure it matches /^[a-f\d]{10,}$/i after cleanup

Example fix

// before
await fetchThread(page, message.messageId); // wrong id type
// after
await fetchThread(page, thread.threadId); // thread id from gmail search
Defensive patterns

Strategy: validation

Validate before calling

const isThreadRef = (v) => typeof v === 'string' && (/^[a-f\d]{10,}$/i.test(v.trim()) || /\/[a-f\d]{10,}$/i.test(v.trim()) || /^#thread-f:\d+$/.test(v.trim()));

Type guard

function isGmailThreadId(v) { if (typeof v !== 'string') return false; const raw = v.trim(); return /^[a-f\d]{10,}$/i.test(raw) || /\/[a-f\d]{10,}$/i.test(raw) || /^#thread-f:\d+$/.test(raw); }

Try / catch

try { await fetchThread(page, id); } catch (e) { if (e instanceof ArgumentError) { console.error('Use a thread id from `gmail search` or a thread URL'); return; } throw e; }

Prevention

When it happens

Trigger: fetchThread(page, target) with a message id instead of a thread id; passing a subject line or partial id; passing a numeric id that is too short; passing a URL with extra query params after the id.

Common situations: Confusing Gmail message ids with thread ids (they differ); copying a URL fragment with trailing parameters; using ids from a different system (e.g. IMAP UIDs).

Related errors


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