{"record":{"id":"66ff9b95f58d93a2","repo":"jackwener/OpenCLI","slug":"gemini-visible-turns-returned-a-malformed-row","errorCode":null,"errorMessage":"Gemini visible turns returned a malformed row","messagePattern":"Gemini visible turns returned a malformed row","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gemini/utils.js","lineNumber":1191,"sourceCode":"        return false;\n    const clicked = await page.evaluate(clickGeminiConversationByTitleScript(normalizedQuery));\n    if (clicked)\n        await page.wait(1);\n    return !!clicked;\n}\nexport async function getGeminiVisibleTurns(page) {\n    const turns = await getGeminiStructuredTurns(page);\n    if (Array.isArray(turns) && turns.length > 0)\n        return turns;\n    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)","sourceCodeStart":1173,"sourceCodeEnd":1209,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/utils.js#L1173-L1209","documentation":"Thrown by getGeminiStructuredTurns when the getTurnsScript page.evaluate result contains a row that is not an object with string Role and Text fields. The library strictly validates every visible turn before collapsing adjacent turns, so any malformed turn aborts the whole transcript read.","triggerScenarios":"Reading the transcript when the visible-turns extraction returns entries like { Role: null }, missing Text, or non-object items — typically because Gemini's conversation DOM changed (new turn wrapper elements, embedded widgets, code blocks) or because the page was still rendering while polled.","commonSituations":"Gemini UI update altering turn containers; responses containing special blocks (images, tools, thinking panels) that the extraction script mis-shapes; reading a half-rendered streaming response; locale variants with different markup.","solutions":["Retry the read after a short wait so the conversation DOM settles.","Log/dump the offending raw turn from getTurnsScript and update its selectors to the current DOM.","Skip non-conforming turns inside the in-page script instead of returning them.","Catch CommandExecutionError and fall back to getGeminiTranscriptLines (plain strings) for a less strict representation."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isGeminiTurn(t) {\n  return typeof t === 'object' && t !== null &&\n    typeof t.Role === 'string' && typeof t.Text === 'string';\n}","tryCatchPattern":"try {\n  turns = await getGeminiStructuredTurns(page);\n} catch (e) {\n  if (String(e.message).includes('malformed row')) {\n    lines = await getGeminiTranscriptLines(page); // fallback representation\n  } else throw e;\n}","preventionTips":["Read turns only after the response finishes streaming (isGenerating false).","Fall back to transcript lines when structured turns fail validation.","Update turn-extraction selectors after Gemini UI updates.","Retry once after a short wait before failing."],"tags":["gemini","dom-scraping","schema-validation","page-evaluate"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}