{"record":{"id":"f294b88d9745a209","repo":"jackwener/OpenCLI","slug":"prepared-reason-could-not-find-gemini-compose","errorCode":null,"errorMessage":"prepared?.reason || 'Could not find Gemini composer'","messagePattern":"prepared\\?\\.reason \\|\\| 'Could not find Gemini composer'","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gemini/utils.js","lineNumber":1300,"sourceCode":"                userAnchorTurn: findLastUserTurn(current.turns),\n                reason: 'composer_transcript',\n            };\n        }\n    }\n    return null;\n}\nexport async function sendGeminiMessage(page, text) {\n    await ensureGeminiPage(page);\n    let prepared;\n    for (let attempt = 0; attempt < GEMINI_COMPOSER_PREPARE_ATTEMPTS; attempt += 1) {\n        prepared = await page.evaluate(prepareComposerScript());\n        if (prepared?.ok)\n            break;\n        if (attempt < GEMINI_COMPOSER_PREPARE_ATTEMPTS - 1)\n            await page.wait(GEMINI_COMPOSER_PREPARE_WAIT_SECONDS);\n    }\n    if (!prepared?.ok) {\n        throw new CommandExecutionError(prepared?.reason || 'Could not find Gemini composer');\n    }\n    let hasText = false;\n    if (page.nativeType) {\n        try {\n            await page.nativeType(text);\n            await page.wait(0.2);\n            const nativeState = await page.evaluate(composerHasTextScript());\n            hasText = !!nativeState?.hasText;\n        }\n        catch { }\n    }\n    if (!hasText) {\n        const fallbackState = await page.evaluate(insertComposerTextFallbackScript(text));\n        hasText = !!fallbackState?.hasText;\n    }\n    if (!hasText) {\n        throw new CommandExecutionError('Failed to insert text into Gemini composer');\n    }","sourceCodeStart":1282,"sourceCodeEnd":1318,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/utils.js#L1282-L1318","documentation":"Thrown by sendGeminiMessage after prepareComposerScript fails on every retry (GEMINI_COMPOSER_PREPARE_ATTEMPTS attempts). prepared.reason carries the in-page failure cause (e.g. composer not found, composer disabled); the fallback message is used when no reason was reported. It means the library could not get the Gemini composer into a ready-to-type state.","triggerScenarios":"sendGeminiMessage on a page where the composer never becomes ready: page not loaded/logged out, dialog or overlay covering the composer, composer element not matching locators after a UI change, or the prepare script reporting a specific failure reason each attempt.","commonSituations":"Session expired so Gemini shows a login wall; a cookie/consent banner blocks interaction; Gemini UI redesign changes composer markup; navigating too quickly after page.goto; network throttling keeps the app from hydrating within the retry window.","solutions":["Read prepared.reason from logs — it names the exact in-page failure; fix that root cause first.","Verify you are logged into Gemini and no overlay/dialog is present before sending.","Increase GEMINI_COMPOSER_PREPARE_ATTEMPTS or GEMINI_COMPOSER_PREPARE_WAIT_SECONDS for slow environments.","Reload the page (ensureGeminiPage / fresh goto) and retry sendGeminiMessage.","Update buildGeminiComposerLocatorScript selectors if Gemini's markup changed."],"exampleFix":"// before\nawait sendGeminiMessage(page, text);\n// after\nawait ensureGeminiPage(page);\nawait page.wait(2); // let overlays clear and composer hydrate\ntry {\n  await sendGeminiMessage(page, text);\n} catch (e) {\n  if (e.message.includes('Could not find Gemini composer')) { await page.reload(); await sendGeminiMessage(page, text); }\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"// confirm the composer is interactable before sending\nconst ready = await page.evaluate(`(() => { const el = document.querySelector('rich-textarea, [contenteditable=\"true\"]'); return !!el && !el.hasAttribute('disabled') && !document.querySelector('[role=\"dialog\"]'); })()`);\nif (!ready) { await page.wait(2); }","typeGuard":null,"tryCatchPattern":"try {\n  await sendGeminiMessage(page, text);\n} catch (e) {\n  const reason = e.cause || e.message;\n  if (String(reason).includes('Gemini composer')) {\n    await ensureGeminiPage(page); // fresh load clears overlays/login walls\n    await sendGeminiMessage(page, text);\n  } else throw e;\n}","preventionTips":["Check login/session validity before long automation runs.","Dismiss cookie/consent banners before interacting with the page.","Tune GEMINI_COMPOSER_PREPARE_ATTEMPTS/WAIT for slow networks.","Log prepared.reason to catch UI-markup drift early."],"tags":["gemini","browser-automation","dom-selector","composer"],"backgroundTag":"dom-element-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}