karatelabs/karate · error · RuntimeException
CDP error
Error message
CDP error: {message} What it means
CdpClient.send() rethrows non-timeout failures from the async send: if the cause is a RuntimeException it propagates directly; otherwise it is wrapped as 'CDP error: <cause message>'. This is the generic wrapper for any CDP command failure that is not a timeout or already a RuntimeException.
Solutions
- Inspect the chained cause (getCause()) for the root problem — socket closed, browser crashed, etc.
- Verify the browser is still running; relaunch the driver if the session died
- Check CI stability: resource limits (memory) that kill the browser mid-run
- Retry flaky steps; wrap driver interactions with retry for transient socket failures
Example fix
// before
CdpResponse resp = client.method("Page.navigate").param("url", url).send(); // browser died -> 'CDP error'
// after: guard with liveness check
if (karate.driver.isTerminated() == false) {
CdpResponse resp = client.method("Page.navigate").param("url", url).send();
} else {
karate.driver = karate.driverManager.restart();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (driver.isTerminated()) { driver = restartDriver(); } // skip send on dead session Type guard
null
Try / catch
try { CdpResponse r = client.method(m).send(); }
catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("CDP error:")) {
logger.error("CDP root cause:", e.getCause());
throw new DriverException("browser session unhealthy", e.getCause());
}
throw e;
} Prevention
- Inspect the chained cause for the true failure
- Relaunch drivers after browser crashes instead of reusing them
- Harden CI against browser OOM kills (memory limits)
- Retry transient socket failures
When it happens
Trigger: Underlying sendAsync fails with a checked/non-runtime cause (IO errors, closed websocket wrapped in CompletionException); any unexpected completion exception from the CDP future chain.
Common situations: Websocket closed mid-command (browser crashed or exited); IO errors on the DevTools socket in flaky CI environments; internal client failures surfacing through the CompletionException unwrap path.
Related errors
- CDP connection failed readiness check
- CDP timeout for
- browser did not return a browserContextId
- readyState check exception
- dialog accept failed
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/07f20b2cbe440cb7.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpClient.java:275
}
// Send methods
/**
* Blocking send with response.
*/
CdpResponse send(CdpMessage message) {
try {
return sendAsync(message).join();
} catch (CompletionException e) {
Throwable cause = e.getCause();
if (cause instanceof TimeoutException) {
throw new RuntimeException("CDP timeout for: " + message.getMethod());
}
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new RuntimeException("CDP error: " + cause.getMessage(), cause);
}
}
/**
* Async send with response tracking.
*/
CompletableFuture<CdpResponse> sendAsync(CdpMessage message) {
// Fail fast if connection is closed
if (!ws.isOpen()) {
return CompletableFuture.failedFuture(
new WsException(WsException.Type.CONNECTION_CLOSED, "websocket not open"));
}
CompletableFuture<CdpResponse> future = new CompletableFuture<>();
int messageId = message.getId();
pending.put(messageId, new PendingRequest(future, message.getMethod()));
String json = message.toJson();View on GitHub (pinned to a22eb90246)