jackwener/OpenCLI · error · CommandExecutionError

prepared?.reason || 'Could not find Gemini composer'

Error message

prepared?.reason || 'Could not find Gemini composer'

What it means

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.

Source

Thrown at clis/gemini/utils.js:1300

                userAnchorTurn: findLastUserTurn(current.turns),
                reason: 'composer_transcript',
            };
        }
    }
    return null;
}
export async function sendGeminiMessage(page, text) {
    await ensureGeminiPage(page);
    let prepared;
    for (let attempt = 0; attempt < GEMINI_COMPOSER_PREPARE_ATTEMPTS; attempt += 1) {
        prepared = await page.evaluate(prepareComposerScript());
        if (prepared?.ok)
            break;
        if (attempt < GEMINI_COMPOSER_PREPARE_ATTEMPTS - 1)
            await page.wait(GEMINI_COMPOSER_PREPARE_WAIT_SECONDS);
    }
    if (!prepared?.ok) {
        throw new CommandExecutionError(prepared?.reason || 'Could not find Gemini composer');
    }
    let hasText = false;
    if (page.nativeType) {
        try {
            await page.nativeType(text);
            await page.wait(0.2);
            const nativeState = await page.evaluate(composerHasTextScript());
            hasText = !!nativeState?.hasText;
        }
        catch { }
    }
    if (!hasText) {
        const fallbackState = await page.evaluate(insertComposerTextFallbackScript(text));
        hasText = !!fallbackState?.hasText;
    }
    if (!hasText) {
        throw new CommandExecutionError('Failed to insert text into Gemini composer');
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read prepared.reason from logs — it names the exact in-page failure; fix that root cause first.
  2. Verify you are logged into Gemini and no overlay/dialog is present before sending.
  3. Increase GEMINI_COMPOSER_PREPARE_ATTEMPTS or GEMINI_COMPOSER_PREPARE_WAIT_SECONDS for slow environments.
  4. Reload the page (ensureGeminiPage / fresh goto) and retry sendGeminiMessage.
  5. Update buildGeminiComposerLocatorScript selectors if Gemini's markup changed.

Example fix

// before
await sendGeminiMessage(page, text);
// after
await ensureGeminiPage(page);
await page.wait(2); // let overlays clear and composer hydrate
try {
  await sendGeminiMessage(page, text);
} catch (e) {
  if (e.message.includes('Could not find Gemini composer')) { await page.reload(); await sendGeminiMessage(page, text); }
  else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// confirm the composer is interactable before sending
const ready = await page.evaluate(`(() => { const el = document.querySelector('rich-textarea, [contenteditable="true"]'); return !!el && !el.hasAttribute('disabled') && !document.querySelector('[role="dialog"]'); })()`);
if (!ready) { await page.wait(2); }

Try / catch

try {
  await sendGeminiMessage(page, text);
} catch (e) {
  const reason = e.cause || e.message;
  if (String(reason).includes('Gemini composer')) {
    await ensureGeminiPage(page); // fresh load clears overlays/login walls
    await sendGeminiMessage(page, text);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f294b88d9745a209. Report an issue: GitHub.