karatelabs/karate · error · RuntimeException

CDP connection failed readiness check

Error message

CDP connection failed readiness check: {message}

What it means

After opening the DevTools websocket, waitForReady sends a probe CDP command (Browser.getVersion). Any exception during that handshake is wrapped as 'CDP connection failed readiness check: <cause message>'. The connection was established but the browser did not answer the readiness probe correctly.

Solutions

  1. Read the wrapped cause message (e.getMessage()) — it names the real failure (connection reset, CDP error, etc.) and fix that
  2. Verify the browser executable path launches a supported Chrome/Chromium/Edge version
  3. Kill stale processes holding the DevTools port and retry
  4. In containers, add required flags (e.g. --no-sandbox) and ensure shared memory/deps are present
  5. Disable proxies for localhost so the DevTools websocket is not intercepted

Example fix

// before: wrong binary
karate.configure("driver", { type: 'chrome', executable: '/usr/bin/chromium-browser' }); // stale wrapper that exits
// after: valid supported binary
karate.configure("driver", { type: 'chrome', executable: '/usr/bin/google-chrome' });
Defensive patterns

Strategy: retry

Validate before calling

// pre-check the DevTools endpoint before connecting
Socket s = new Socket();
boolean ok = s.isConnected(); // after s.connect(new InetSocketAddress("localhost", port), 2000)
s.close();

Type guard

null

Try / catch

try { connect(); }
catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("CDP connection failed readiness check")) {
        retryWithBackoff(3, this::connect); // relaunch browser each attempt
    } else throw e;
}

Prevention

When it happens

Trigger: Browser closes or crashes immediately after launch (port raced, wrong executable); wrong websocket endpoint URL; the browser responds with a CDP error to the readiness command; a non-Chrome/unsupported browser on the DevTools port; proxy or firewall interfering with the local DevTools socket.

Common situations: chrome/edge binary path misconfigured so something else listens on the port; browser version mismatch with the driver's CDP expectations; browser exits early in CI containers (missing deps, no sandbox flags); stale browser process occupying the debug port.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/c0d5873a81fb1a51. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpClient.java:131

    /**
     * Wait for CDP to be ready by sending a simple command.
     * This verifies the WebSocket connection is fully established and CDP is responsive.
     */
    private void waitForReady() {
        try {
            // Use a shorter timeout for readiness check
            Duration readyTimeout = defaultTimeout.compareTo(Duration.ofSeconds(10)) > 0
                    ? Duration.ofSeconds(10) : defaultTimeout;
            CdpMessage message = new CdpMessage(this, nextId(), "Browser.getVersion");
            message.timeout(readyTimeout);
            CdpResponse response = send(message);
            if (response.isError()) {
                logger.warn("CDP readiness check returned error: {}", response.getErrorMessage());
            } else {
                logger.debug("CDP ready, browser: {}", response.getResult().get("product"));
            }
        } catch (Exception e) {
            throw new RuntimeException("CDP connection failed readiness check: " + e.getMessage(), e);
        }
    }

    private void setupMessageHandler() {
        ws.onMessage(frame -> {
            if (frame.isText()) {
                handleMessage(frame.getText());
            }
        });
        ws.onClose(() -> {
            // Complete all pending futures exceptionally
            for (PendingRequest pr : pending.values()) {
                pr.future.completeExceptionally(
                        new WsException(WsException.Type.CONNECTION_CLOSED, "websocket closed"));
            }
            pending.clear();
        });
        ws.onError(error -> {

View on GitHub (pinned to a22eb90246)