karatelabs/karate · error
chrome process died while waiting for page targets
Error message
chrome process died while waiting for page targets (exit code: {}) What it means
WARN log from CdpLauncher.waitForWebSocketUrl when the launched Chrome process exits while Karate is polling the DevTargets HTTP endpoint to discover the WebSocket debugger URL. The method returns null, which causes start() to fail launching the driver.
Solutions
- Match the exit code (logged) against Chrome startup failure docs; common codes indicate bad flags or missing deps.
- In Docker/root, add --no-sandbox (or run as non-root) via driver addOptions.
- Use a fresh, writable user-data-dir to avoid profile lock/corruption issues.
- Check the debugging port isn't occupied and the Chrome version is compatible with the Karate/CDP driver.
- Increase available memory in CI; Chrome often dies from OOM during startup.
Example fix
// before
karate.configure('driver', { type: 'chrome' });
// after (containerized / CI environment)
karate.configure('driver', {
type: 'chrome',
addOptions: ['--no-sandbox', '--disable-dev-shm-usage'],
userDataDir: '/tmp/karate-chrome-profile'
}); Defensive patterns
Strategy: try-catch
Validate before calling
// pre-launch sanity checks in CI
assert new File("/dev/shm").getFreeSpace() > 256 * 1024 * 1024; // ample shm
// ensure debug port is free
try (var s = new java.net.ServerSocket(9222)) { /* free */ } catch (IOException e) { throw new IllegalStateException("port 9222 in use"); } Try / catch
try {
driver = Driver.start("chrome");
} catch (RuntimeException e) {
// launcher returned null websocket url — chrome died at startup
logger.error("chrome failed to start: {}", e.getMessage());
throw new SkipException("browser unavailable", e);
} Prevention
- Add --no-sandbox --disable-dev-shm-usage in Docker/root environments.
- Pin a Chrome version known to work with your karate-core version.
- Use a fresh user-data-dir per run to avoid profile corruption.
- Ensure CI runners have enough memory for Chrome startup.
When it happens
Trigger: During startup, process.isAlive() becomes false while waiting for the page-targets list — Chrome crashed immediately after launch, failed to bind its debugging port, or was killed by the OS/CI.
Common situations: Missing --no-sandbox in root/Docker containers; Chrome version incompatibility with the CDP protocol; corrupted user-data-dir; port conflicts with an existing Chrome instance; OOM-kill in constrained CI memory.
Related errors
- at least one feature file is required
- browser did not return a browserContextId
- browser did not return a targetId for context
- CDP connection failed readiness check
- CDP error
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/12a93d290a58a02c.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpLauncher.java:235
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
long startTime = System.nanoTime();
long timeoutNanos = timeoutMs * 1_000_000L;
String url = "http://" + host + ":" + port + "/json";
int intervalMs = 250;
int attemptCount = 0;
// Use elapsed time instead of attempt count to handle variable request durations
// Always make at least one attempt even if timeout is very small
while (attemptCount == 0 || (System.nanoTime() - startTime) < timeoutNanos) {
attemptCount++;
// Check if process died
if (process != null && !process.isAlive()) {
int exitCode = process.getExitCode();
logger.warn("chrome process died while waiting for page targets (exit code: {})", exitCode);
return null;
}
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(5))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
List<Map<String, Object>> targets = (List<Map<String, Object>>) JSONValue.parse(response.body());
if (targets != null && !targets.isEmpty()) {
// Look for a valid page target (same logic as v1)
for (Map<String, Object> target : targets) {
String targetUrl = (String) target.get("url");
String targetType = (String) target.get("type");View on GitHub (pinned to a22eb90246)