{"record":{"id":"85c92176b6bc0b44","repo":"jackwener/OpenCLI","slug":"gmail-fetch-data-response-had-an-unexpected-shape","errorCode":null,"errorMessage":"Gmail fetch-data response had an unexpected shape","messagePattern":"Gmail fetch-data response had an unexpected shape","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gmail/utils.js","lineNumber":243,"sourceCode":"  const out = [];\n  for (const wrapper of Array.isArray(record?.[13]) ? record[13] : []) {\n    const node = Array.isArray(wrapper?.[0]) ? wrapper[0] : null;\n    const data = Array.isArray(node?.[3]) ? node[3] : null;\n    const attachmentId = cleanString(node?.[1]);\n    if (!data || !attachmentId) continue;\n    out.push({\n      attachmentId,\n      name: cleanString(data[2]) || null,\n      mimeType: cleanString(data[3]) || null,\n      size: Number.isFinite(Number(data[4])) ? Number(data[4]) : null,\n    });\n  }\n  return out;\n}\n\nexport function parseFetchData(body) {\n  if (!Array.isArray(body) || !Array.isArray(body[1])) {\n    throw new CommandExecutionError('Gmail fetch-data response had an unexpected shape');\n  }\n  const messages = [];\n  for (const threadWrapper of body[1]) {\n    const threadId = cleanString(threadWrapper?.[0]).replace(/^#/, '');\n    const rows = Array.isArray(threadWrapper?.[2]) ? threadWrapper[2] : [];\n    for (const wrapper of rows) {\n      const messageId = cleanString(wrapper?.[0]).replace(/^#/, '');\n      const record = Array.isArray(wrapper?.[1]) ? wrapper[1] : null;\n      if (!threadId || !messageId || !record) {\n        throw new CommandExecutionError('Gmail fetch-data returned a malformed message');\n      }\n      const from = senderFromRecord(record);\n      const attachments = parseAttachments(record);\n      messages.push({\n        messageId,\n        legacyMessageId: cleanString(record[34]) || null,\n        threadId,\n        subject: cleanString(record[4]) || '(no subject)',","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gmail/utils.js#L225-L261","documentation":"parseFetchData validates the Gmail fetch-data (/i/fd) payload: it must be an array whose element [1] is an array of thread wrappers. Anything else triggers this CommandExecutionError. The /fd wire format differs from /bv, so this guard is the fetch-data counterpart of the batch-view shape check and fires when the response does not match the known layout.","triggerScenarios":"fetchThread captures a /i/fd response where body is not an array or body[1] is not an array — Gmail protocol change, capture matched a different /sync request, or a partial/interstitial payload was captured.","commonSituations":"Gmail web-app updates altering the fd envelope, opening a thread right as the page navigates so an unrelated fd response is captured, stale Gmail bundles after a deploy.","solutions":["Retry the command; if persistent, capture the payload and report it for a parser update.","Update opencli to the latest version matching Gmail's current fd format.","Reload Gmail, reopen the thread in the UI, then rerun so a clean fd response is captured.","Avoid concurrent Gmail navigation while fetchThread's capture window is open."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate the thread target before opening so a wrong navigation doesn't yield a stray fd payload\nif (!/^(thread-f:\\d+|[a-f\\d]{10,}|#?\\d+)$/i.test(target)) {\n  throw new Error('target must be a Gmail thread id or thread URL');\n}","typeGuard":"function isFetchDataEnvelope(body) {\n  return Array.isArray(body) && Array.isArray(body[1]);\n}","tryCatchPattern":"try {\n  messages = await gmailThread(threadId);\n} catch (error) {\n  if (String(error.message).includes('fetch-data response had an unexpected shape')) {\n    await page.reload(); // re-navigate cleanly, then retry once\n    messages = await gmailThread(threadId);\n  } else throw error;\n}","preventionTips":["Open one thread at a time and avoid tab navigation during the fd capture window.","Keep the CLI updated for Gmail fd-format changes.","Pass thread ids from `gmail search` output or thread URLs, not hand-built values.","Retry once before reporting a persistent shape mismatch."],"tags":["gmail","fetch-data","schema-validation","response-shape"],"backgroundTag":"unexpected-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}