{"record":{"id":"cf306c2296613824","repo":"jackwener/OpenCLI","slug":"gemini-transcript-lines-returned-a-malformed-row","errorCode":null,"errorMessage":"Gemini transcript lines returned a malformed row","messagePattern":"Gemini transcript lines returned a malformed row","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gemini/utils.js","lineNumber":1201,"sourceCode":"    const lines = await getGeminiTranscriptLines(page);\n    return lines.map((line) => ({ Role: 'System', Text: line }));\n}\nasync function getGeminiStructuredTurns(page) {\n    await ensureGeminiPage(page);\n    const raw = requireGeminiArrayResult(await page.evaluate(getTurnsScript()), 'Gemini visible turns');\n    for (const turn of raw) {\n        if (!isObjectRecord(turn) || typeof turn.Role !== 'string' || typeof turn.Text !== 'string') {\n            throw new CommandExecutionError('Gemini visible turns returned a malformed row');\n        }\n    }\n    const turns = collapseAdjacentGeminiTurns(raw);\n    return Array.isArray(turns) ? turns : [];\n}\nexport async function getGeminiTranscriptLines(page) {\n    await ensureGeminiPage(page);\n    const lines = requireGeminiArrayResult(await page.evaluate(getTranscriptLinesScript()), 'Gemini transcript lines');\n    if (!lines.every((line) => typeof line === 'string')) {\n        throw new CommandExecutionError('Gemini transcript lines returned a malformed row');\n    }\n    return lines;\n}\nexport async function waitForGeminiTranscript(page, attempts = 5) {\n    let lines = [];\n    for (let index = 0; index < attempts; index += 1) {\n        lines = await getGeminiTranscriptLines(page);\n        if (lines.length > 0)\n            return lines;\n        if (index < attempts - 1)\n            await page.wait(1);\n    }\n    return lines;\n}\nexport async function getLatestGeminiAssistantResponse(page) {\n    await ensureGeminiPage(page);\n    const turns = await getGeminiVisibleTurns(page);\n    const assistantTurn = [...turns].reverse().find((turn) => turn.Role === 'Assistant');","sourceCodeStart":1183,"sourceCodeEnd":1219,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/utils.js#L1183-L1219","documentation":"Thrown by getGeminiTranscriptLines when requireGeminiArrayResult succeeds but the returned array contains non-string entries. The transcript-lines script must yield an array of plain strings; any object, null, or number in the array triggers this CommandExecutionError.","triggerScenarios":"Calling transcript-line extraction when getTranscriptLinesScript() returns mixed content (e.g. nested elements serialized as objects, undefined for empty line containers) because Gemini's transcript DOM changed or the page was polled mid-render.","commonSituations":"Gemini update changing line container structure; transcript containing rich nodes (images/code) that the script maps to objects; stale page snapshot from before hydration; mocked data of the wrong shape.","solutions":["Retry after a short wait for the transcript to finish rendering.","Inspect raw output of getTranscriptLinesScript and coerce/map entries to strings inside the in-page script (e.g. el.textContent.trim()).","Filter out null/undefined entries in the extraction script before returning.","Catch CommandExecutionError and fall back to the structured-turns API instead."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isStringArray(v) {\n  return Array.isArray(v) && v.every((x) => typeof x === 'string');\n}","tryCatchPattern":"try {\n  lines = await getGeminiTranscriptLines(page);\n} catch (e) {\n  if (String(e.message).includes('malformed row')) lines = [];\n  else throw e;\n}","preventionTips":["Poll only after the transcript container is present and stable.","Validate mocked data with isStringArray in tests.","Keep extraction script in sync with Gemini transcript DOM changes.","Prefer the structured-turns API when line-level detail isn't required."],"tags":["gemini","dom-scraping","type-mismatch","page-evaluate"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}