jackwener/OpenCLI · error · CommandExecutionError
Gmail batch-view returned a malformed thread at index ${inde
Error message
Gmail batch-view returned a malformed thread at index ${index} What it means
Within parseBatchView, each row of body[2] should be a wrapper whose element [0] is a thread record with at least 5 fields (subject, snippet, timestamp, thread id, message list). If the wrapper is not an array, record is null, or record.length < 5, this CommandExecutionError is thrown with the row index. It means Gmail returned a batch-view row the parser cannot read as a thread.
Source
Thrown at clis/gmail/utils.js:141
function senderFromSummary(message) {
return addressRef(Array.isArray(message) ? message[1] : null);
}
function labelIdsFromMessages(messages) {
return [...new Set((Array.isArray(messages) ? messages : [])
.flatMap((message) => Array.isArray(message?.[10]) ? message[10] : [])
.filter((label) => typeof label === 'string' && label.startsWith('^')))];
}
export function parseBatchView(body) {
if (!Array.isArray(body) || body.length !== 19) {
throw new CommandExecutionError('Gmail batch-view response had an unexpected shape');
}
const rows = Array.isArray(body[2]) ? body[2] : [];
return rows.map((wrapper, index) => {
const record = Array.isArray(wrapper?.[0]) ? wrapper[0] : null;
if (!record || record.length < 5) {
throw new CommandExecutionError(`Gmail batch-view returned a malformed thread at index ${index}`);
}
const threadId = cleanString(record[3]).replace(/^#/, '');
const messages = Array.isArray(record[4]) ? record[4] : [];
const latest = messages.at(-1);
const sender = senderFromSummary(latest);
if (!threadId) throw new CommandExecutionError(`Gmail batch-view returned a thread without an id at index ${index}`);
const labels = labelIdsFromMessages(messages);
return {
threadId,
subject: cleanString(record[0]) || '(no subject)',
from: sender?.address || null,
fromName: sender?.name || null,
snippet: cleanString(record[1]) || null,
messageCount: messages.length,
unread: labels.includes('^u'),
starred: labels.includes('^t'),
date: gmailDate(record[2], `thread ${threadId}`),
labels,View on GitHub (pinned to 49907e53dc)
Solutions
- Refine the search query to exclude the problematic thread (e.g. add -in:trash or a label filter) and rerun.
- Retry; transient placeholder rows during live sync often disappear after Gmail settles.
- Update opencli so parseBatchView tolerates/handles the new row shape.
- Reload Gmail and rerun to force a fresh batch-view payload.
Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
function isThreadRecord(wrapper) {
const record = Array.isArray(wrapper?.[0]) ? wrapper[0] : null;
return Array.isArray(record) && record.length >= 5;
} Try / catch
try {
threads = await gmailSearch(query);
} catch (error) {
const m = String(error.message).match(/malformed thread at index (\d+)/);
if (m) {
// rerun with a query that excludes the bad row, or retry after sync settles
await sleep(1500);
threads = await gmailSearch(query);
} else throw error;
} Prevention
- Avoid searching while threads are being deleted/moved in another session.
- Exclude volatile folders (trash, drafts) from queries to reduce placeholder rows.
- Retry once — placeholder rows are frequently transient sync artifacts.
- Report persistent index-specific failures with the query used, so the parser can be adapted.
When it happens
Trigger: A /i/bv response containing a row whose record array is missing or shorter than 5 elements — e.g. a placeholder/tombstone row for a deleted or inaccessible thread, or a Gmail payload-format change affecting individual rows.
Common situations: Searches touching recently deleted/undeleting threads, threads in accounts with restricted access, Gmail A/B experiments changing per-row encoding, sync rows for archived/draft placeholders.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Gmail batch-view returned a thread without an id at index ${
- Gmail returned a malformed label at index ${index}
- Gmail batch-view response had an unexpected shape
- Gmail fetch-data response had an unexpected shape
- Gmail fetch-data returned a malformed message
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e1811553e733a814.
Report an issue: GitHub.