{"record":{"id":"e1811553e733a814","repo":"jackwener/OpenCLI","slug":"gmail-batch-view-returned-a-malformed-thread-at-in","errorCode":null,"errorMessage":"Gmail batch-view returned a malformed thread at index ${index}","messagePattern":"Gmail batch-view returned a malformed thread at index (.+?)","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gmail/utils.js","lineNumber":141,"sourceCode":"function senderFromSummary(message) {\n  return addressRef(Array.isArray(message) ? message[1] : null);\n}\n\nfunction labelIdsFromMessages(messages) {\n  return [...new Set((Array.isArray(messages) ? messages : [])\n    .flatMap((message) => Array.isArray(message?.[10]) ? message[10] : [])\n    .filter((label) => typeof label === 'string' && label.startsWith('^')))];\n}\n\nexport function parseBatchView(body) {\n  if (!Array.isArray(body) || body.length !== 19) {\n    throw new CommandExecutionError('Gmail batch-view response had an unexpected shape');\n  }\n  const rows = Array.isArray(body[2]) ? body[2] : [];\n  return rows.map((wrapper, index) => {\n    const record = Array.isArray(wrapper?.[0]) ? wrapper[0] : null;\n    if (!record || record.length < 5) {\n      throw new CommandExecutionError(`Gmail batch-view returned a malformed thread at index ${index}`);\n    }\n    const threadId = cleanString(record[3]).replace(/^#/, '');\n    const messages = Array.isArray(record[4]) ? record[4] : [];\n    const latest = messages.at(-1);\n    const sender = senderFromSummary(latest);\n    if (!threadId) throw new CommandExecutionError(`Gmail batch-view returned a thread without an id at index ${index}`);\n    const labels = labelIdsFromMessages(messages);\n    return {\n      threadId,\n      subject: cleanString(record[0]) || '(no subject)',\n      from: sender?.address || null,\n      fromName: sender?.name || null,\n      snippet: cleanString(record[1]) || null,\n      messageCount: messages.length,\n      unread: labels.includes('^u'),\n      starred: labels.includes('^t'),\n      date: gmailDate(record[2], `thread ${threadId}`),\n      labels,","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gmail/utils.js#L123-L159","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"function isThreadRecord(wrapper) {\n  const record = Array.isArray(wrapper?.[0]) ? wrapper[0] : null;\n  return Array.isArray(record) && record.length >= 5;\n}","tryCatchPattern":"try {\n  threads = await gmailSearch(query);\n} catch (error) {\n  const m = String(error.message).match(/malformed thread at index (\\d+)/);\n  if (m) {\n    // rerun with a query that excludes the bad row, or retry after sync settles\n    await sleep(1500);\n    threads = await gmailSearch(query);\n  } else throw error;\n}","preventionTips":["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."],"tags":["gmail","schema-validation","batch-view","malformed-row"],"backgroundTag":"unexpected-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}