karatelabs/karate · error · DialogOpenedException
dialog is blocking Runtime.evaluate
Error message
dialog is blocking Runtime.evaluate
What it means
Karate detected that a JavaScript dialog (alert/confirm/prompt/beforeunload) is currently open and unhandled. While such a dialog is open, Chrome cancels any Runtime.evaluate, so Karate fails fast with DialogOpenedException instead of hanging until the 30s CDP timeout. The fix on the user side is to register an onDialog handler or auto-answer dialogs via dialog(true|false).
Solutions
- Call driver.dialog(true) (accept) or driver.dialog(false) (dismiss) before steps that may open dialogs
- Register an onDialog handler to programmatically handle dialogs as they appear
- Dismiss the current dialog first (via the dialog API) before issuing further script() calls
- If the dialog comes from beforeunload, use CDP Page.setBypassCSP or launch flags / evaluate-on-navigation settings to suppress it
Example fix
// before
driver.click("#delete-button"); // fires confirm()
driver.script("document.title"); // DialogOpenedException
// after
driver.dialog(true); // auto-accept dialogs
driver.click("#delete-button");
String title = driver.script("document.title"); Defensive patterns
Strategy: try-catch
Validate before calling
// configure dialog auto-handling before any navigation driver.dialog(false); // auto-dismiss all dialogs, prevents blocking
Try / catch
try { String v = driver.script(expr); } catch (DialogOpenedException e) { driver.dialog(true); String v = driver.script(expr); } Prevention
- Always register onDialog() or set dialog(true|false) for pages known to open dialogs
- Enable beforeunload suppression in test profiles
- Never interleave script() calls between a click that may open a dialog and handling it
- Handle dialogs immediately when tests trigger confirm/prompt flows
When it happens
Trigger: Calling driver.script(...)/script() (any JS evaluation) while a native dialog is open and no dialogHandler is registered and the current dialog has not been handled — e.g. the page popped an alert during a previous step.
Common situations: Pages with beforeunload prompts triggered by navigation; sites firing alert() during load or on click; forgetting to set dialog(false)/dialog(true) before interacting with dialog-heavy pages; parallel runs where one thread's dialog blocks subsequent script calls.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- dialog accept failed
- dialog dismiss failed
- dialog handler did not resolve dialog, auto-dismissing
- CDP connection failed readiness check
- CDP timeout for
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a0fea3ce67675f17.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:1837
*/
private CdpResponse cdpEval(String expression) {
return cdpEval(expression, true);
}
/**
* As {@link #cdpEval(String)}, but lets the caller choose the serialization mode.
* {@code returnByValue=false} yields a CDP {@code RemoteObject} handle (its {@code objectId})
* instead of the value — required when the result is a live DOM node that a CDP domain method
* must address by reference (see {@link #objectId(String)}).
*/
private CdpResponse cdpEval(String expression, boolean returnByValue) {
// Fail fast if a dialog is already open and blocking. A pre-existing
// unhandled dialog means any new Runtime.evaluate would be cancelled
// by our Page.javascriptDialogOpening handler (or hang until the 30s
// CDP timeout). Users should register onDialog() or call dialog(true|false)
// before further script activity.
if (dialogHandler == null && currentDialog != null && !currentDialog.isHandled()) {
throw new DialogOpenedException("dialog is blocking Runtime.evaluate");
}
// A destroyed execution context (navigation tore it down) is re-created by Chrome
// within tens of milliseconds, NOT the 500ms element-poll interval. Sleeping the
// full retryInterval per transient error makes every post-navigation eval cost
// ~500ms+, and with wildcard locators / waitUntil polling that snowballs into
// spurious waitUntil/waitFor timeouts under parallel load. Poll fast instead, but
// keep the SAME overall time budget (retryCount * retryInterval) so a genuinely
// slow context swap on a loaded CI box still recovers.
int transientInterval = fastPollInterval();
int maxRetries = fastPollAttempts();
for (int attempt = 0; attempt <= maxRetries; attempt++) {
CdpMessage message = cdp.method("Runtime.evaluate")
.param("expression", expression)
.param("returnByValue", returnByValue);
// Use explicit context ID for reliable frame targeting (see getFrameContext notes)
Integer contextId = getFrameContext();View on GitHub (pinned to a22eb90246)