jackwener/OpenCLI · error · CommandExecutionError
Gemini generation probe failed
Error message
Gemini generation probe failed
What it means
Thrown by isGeminiGenerating when page.evaluate of the isGeneratingExpression script itself throws (navigation, detached execution context, script syntax/runtime error). The original browser error message is preserved as the second argument of CommandExecutionError, and the wrapper normalizes it for callers of the generation probe.
Source
Thrown at clis/gemini/utils.js:2379
}
return urls;
})()
`);
const urls = requireGeminiArrayResult(result, 'Gemini image detection');
if (!urls.every((url) => typeof url === 'string')) {
throw new CommandExecutionError('Gemini image detection returned a malformed result');
}
return urls;
}
/** Cheap generation probe: the snapshot read walks the whole transcript. */
export async function isGeminiGenerating(page) {
let result;
try {
result = await page.evaluate(`(() => ${isGeneratingExpression()})()`);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new CommandExecutionError('Gemini generation probe failed', message);
}
const value = unwrapGeminiEvaluateResult(result, 'Gemini generation probe');
if (typeof value !== 'boolean') {
throw new CommandExecutionError('Gemini generation probe returned a malformed result');
}
return value;
}
export async function waitForGeminiImages(page, beforeUrls, timeoutSeconds) {
const beforeSet = new Set(beforeUrls);
const pollIntervalSeconds = 3;
const maxPolls = Math.max(1, Math.ceil(timeoutSeconds / pollIntervalSeconds));
let lastUrls = [];
let stableCount = 0;
let stillGenerating = false;
for (let index = 0; index < maxPolls; index += 1) {
await page.wait(index === 0 ? 2 : pollIntervalSeconds);
// The text waits already gate on this signal; without it the image wait
// can settle on whatever is on screen mid-generation (#2245). AnView on GitHub (pinned to 49907e53dc)
Solutions
- Retry the probe — navigation-timing races are transient and a re-poll usually succeeds.
- Read the wrapped cause (second arg / error.cause) to identify the underlying evaluate failure.
- Ensure the page isn't navigating during polling; wait for URL stability before probing.
- Add null/DOM guards inside isGeneratingExpression so missing nodes return false instead of throwing.
- Re-create the page/browser if the execution context is permanently gone (tab closed).
Defensive patterns
Strategy: try-catch
Try / catch
let generating = false;
try {
generating = await isGeminiGenerating(page);
} catch (e) {
const cause = e.cause || e.message;
if (String(cause).includes('probe failed')) { await page.wait(1); generating = await isGeminiGenerating(page); }
else throw e;
} Prevention
- Avoid probing during client-side navigation; wait for URL stability.
- Add null guards inside isGeneratingExpression for missing DOM nodes.
- Keep the browser/tab alive for the duration of polling loops.
- Inspect e.cause for the underlying evaluate error when debugging.
When it happens
Trigger: Polling isGeminiGenerating while the page navigates to a new conversation URL (execution context destroyed), the tab crashed/closed, or the in-page expression throws at runtime because expected DOM nodes are absent and the expression doesn't guard them.
Common situations: Race between submission and Gemini's client-side navigation; slow/unstable network causing context loss; headless browser killed mid-poll; Gemini deploying an update mid-session that breaks the probe expression.
Related errors
- Gemini generation probe returned a malformed result
- Gemini conversation list returned a malformed row
- Gemini visible turns returned a malformed row
- Gemini transcript lines returned a malformed row
- Gemini page snapshot returned a malformed result
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4d978cecd36d3cfc.
Report an issue: GitHub.