musistudio/claude-code-router · error · Error
Failed to handle browser dialog
Error message
Failed to handle browser dialog: ${formatError(error)} What it means
A wrapper error thrown when handling a browser dialog (alert/confirm/prompt) via the Electron debugger protocol fails for any underlying reason — the inner error is captured and re-formatted into the message. Root causes include the debugger failing to attach, the dialog already being dismissed, or an unexpected CDP response.
Solutions
- Read the embedded inner error text — it identifies the actual CDP/debugger failure to fix.
- Retry once: dialogs are inherently racy and a retry after re-detecting the dialog often succeeds.
- Ensure no other debugger session (open DevTools, another tool call) holds the webContents.
- Avoid firing multiple dialog-handling calls concurrently on the same tab.
Example fix
// before
await call("browser_handle_dialog", { accept: true, tabId }); // throws if dialog already gone
// after
try {
await call("browser_handle_dialog", { accept: true, tabId });
} catch (e) {
if (String(e.message).includes("Failed to handle browser dialog")) {
const state = await call("browser_snapshot", { tabId }); // dialog already resolved; continue
} else throw e;
} Defensive patterns
Strategy: retry
Try / catch
try { await call("browser_handle_dialog", { accept: true, tabId }); } catch (e) { if (e instanceof Error && e.message.startsWith("Failed to handle browser dialog")) { const snapshot = await call("browser_snapshot", { tabId }); /* dialog likely already resolved; inspect and continue */ } else throw e; } Prevention
- Handle dialogs promptly when detected
- Avoid concurrent dialog calls on one tab
- Close DevTools/other debugger sessions before dialog automation
- Read the inner formatted error to find the CDP root cause
When it happens
Trigger: Calling a browser dialog tool while the debugger cannot attach to the webContents (already attached elsewhere), when the dialog no longer exists by the time the handler acts, or when the CDP command errors/times out.
Common situations: Race between dialog appearance and the handle call; another debugger client (DevTools) is attached; page dismissed the dialog programmatically; concurrent dialog-handling calls on the same tab.
Related errors
- A valid browser automation session is required.
- Browser automation session tab was not found
- Browser automation session tabId does not match the…
- browser_chrome_login_import requires domains or an active…
- Browser event subscription was not found
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/2042837083225912.
Report an issue: GitHub.
Appendix: source
Thrown at packages/electron/src/main/browser-automation-mcp.ts:2310
await withTimeout(webContents.debugger.sendCommand("Page.enable"), defaultJavascriptTimeoutMs, "Timed out enabling browser dialog handling.");
await withTimeout(
webContents.debugger.sendCommand("Page.handleJavaScriptDialog", {
accept,
...(promptText !== undefined ? { promptText } : {})
}),
defaultJavascriptTimeoutMs,
"Timed out handling browser dialog."
);
return {
accepted: accept,
ok: true,
promptText,
session,
title: await webContents.getTitle(),
url: webContents.getURL()
};
} catch (error) {
throw new Error(`Failed to handle browser dialog: ${formatError(error)}`);
} finally {
if (attachedHere && webContents.debugger.isAttached()) {
try {
webContents.debugger.detach();
} catch {
// Ignore detach errors after the dialog is resolved.
}
}
}
}
async function executeJavaScriptWithTimeout<T = unknown>(
webContents: WebContents,
script: string,
timeoutMs: number,
label: string
): Promise<T> {
if (webContents.isDestroyed()) {View on GitHub (pinned to 99f24806c6)