jackwener/OpenCLI · error · CommandExecutionError

Gmail ${operation} response body was unavailable

Error message

Gmail ${operation} response body was unavailable

What it means

This CommandExecutionError is thrown by parseJsonCapture when the captured Gmail /sync response entry has neither a string responsePreview nor responseBodyTruncated === true — i.e. the entry reached the parser with a status of 200 but no usable body at all. waitGmailCaptures is supposed to filter such bodyless entries, so this indicates a race where the capture was read before the response body arrived or the bridge lost the body. The library throws rather than return partial data.

Source

Thrown at clis/gmail/utils.js:105

    .replace(/\n{3,}/g, '\n\n')
    .trim();
}

function parseJsonCapture(entry, operation) {
  const status = Number(entry?.responseStatus || 0);
  if (status === 401 || status === 403) {
    throw new AuthRequiredError(GMAIL_HOST, `Gmail ${operation} returned HTTP ${status}`);
  }
  if (status !== 200) {
    throw new CommandExecutionError(`Gmail ${operation} returned HTTP ${status || 'unknown'}`);
  }
  if (entry?.responseBodyTruncated === true) {
    throw new CommandExecutionError(`Gmail ${operation} response exceeded the browser capture limit`);
  }
  const body = entry?.responsePreview;
  if (Array.isArray(body)) return body;
  if (typeof body !== 'string') {
    throw new CommandExecutionError(`Gmail ${operation} response body was unavailable`);
  }
  try {
    const parsed = JSON.parse(body.replace(/^\)\]\}'\s*/, ''));
    if (!Array.isArray(parsed)) throw new Error('not an array');
    return parsed;
  } catch {
    throw new CommandExecutionError(`Gmail ${operation} returned malformed JSON`);
  }
}

function addressRef(value) {
  if (!Array.isArray(value)) return null;
  const address = cleanString(value[1]);
  if (!address.includes('@')) return null;
  return { address, name: cleanString(value[2]) || null };
}

function senderFromSummary(message) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — the capture race is often transient.
  2. Update the browser bridge to a version that only exposes entries once status+body are complete.
  3. If it recurs, reload Gmail in the browser and rerun so the /sync request completes fully.
  4. Check network speed/proxy; a stalled /sync response can keep the body unavailable past the 10s wait.

Example fix

// user retry wrapper
try {
  threads = await queryThreads(page, query, { limit: 20 });
} catch (error) {
  if (String(error.message).includes('response body was unavailable')) {
    await page.reload();
    threads = await queryThreads(page, query, { limit: 20 });
  } else throw error;
}
Defensive patterns

Strategy: retry

Validate before calling

// confirm the page is settled before running commands
const url = await page.getCurrentUrl();
if (!String(url || '').startsWith('https://mail.google.com/mail/u/')) {
  throw new Error('Gmail is not on the mailbox view; sign in / reload before running commands');
}

Type guard

function hasBody(entry) {
  return typeof entry?.responsePreview === 'string' || entry?.responseBodyTruncated === true;
}

Try / catch

try {
  result = await gmailSearch(query);
} catch (error) {
  if (String(error.message).includes('response body was unavailable')) {
    await sleep(2000); // let the in-flight /sync response settle
    result = await gmailSearch(query); // single retry
  } else throw error;
}

Prevention

When it happens

Trigger: parseJsonCapture receives entry with responseStatus 200, responseBodyTruncated not true, and responsePreview being undefined/null/non-string — e.g. the settled re-read in waitGmailCaptures still returned an in-flight entry, or the bridge dropped the body of the /i/bv or /i/fd response.

Common situations: Slow Gmail /sync responses (large mailbox, slow network) racing the capture reads; browser bridge versions that emit status before body; capture queue drained mid-flight during pagination clicks.

Related errors


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