karatelabs/karate · warning
pool size but webSocketUrl names a single page — all slots…
Error message
pool size {} but webSocketUrl names a single page — all slots will drive the SAME tab. Pass a browser-level endpoint (see /json/version) for isolated slots: {} What it means
When createDriver() is given a page-level webSocketUrl (does not contain /devtools/browser/) while poolSize > 1, every pooled driver connects to the SAME tab, so parallel scenarios will interfere. The provider logs this warning and falls back to CdpDriver.connect() on that single page instead of connectNewContext().
Solutions
- Use the browser-level webSocketUrl from http://host:port/json/version (contains /devtools/browser/) so each slot gets connectNewContext() and an isolated context
- Set poolSize to 1 if you intentionally share a single page
- Drop the explicit webSocketUrl and let Karate launch the browser itself for pooled runs
Example fix
// before webSocketUrl: 'ws://localhost:9222/devtools/page/ABC123' poolSize: 4 // after webSocketUrl: 'ws://localhost:9222/devtools/browser/GUID-456' poolSize: 4
Defensive patterns
Strategy: validation
Validate before calling
String ws = options.getWebSocketUrl();
if (ws != null && poolSize > 1 && !ws.contains("/devtools/browser/")) {
throw new IllegalArgumentException(
"webSocketUrl must be a browser-level endpoint (/devtools/browser/) when poolSize > 1: " + ws);
} Type guard
boolean isBrowserLevel = ws -> ws != null && ws.contains("/devtools/browser/"); Prevention
- Copy webSocketUrl from /json/version, never /json (page list)
- Keep poolSize 1 only when intentionally sharing one tab
- Prefer letting Karate launch the browser for pooled runs
When it happens
Trigger: Configuring karate with webSocketUrl pointing at a page target from /json/list or /json (contains /devtools/page/) instead of the browser endpoint from /json/version, with poolSize > 1.
Common situations: Copy-pasting a debug ws URL from a single Chrome session; using connectToChrome style config for pooled runs; mixing CDP connect examples with the pool feature.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- currentTargetId fallback to getPages()[0]
- CDP connection failed readiness check
- CDP timeout for
- CDP error
- dialog accept failed
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/4c3dbd4b5f366c72.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java:439
* tab — that is inherent to the request, not something this method can fix.
* </p>
*/
protected Driver createDriver(Map<String, Object> config) {
String type = (String) config.getOrDefault("type", "chrome");
if (W3cBrowserType.isW3cType(type)) {
return W3cDriver.start(config);
}
// CDP (default)
CdpDriverOptions options = CdpDriverOptions.fromMap(config);
String wsUrl = options.getWebSocketUrl();
if (wsUrl == null || wsUrl.isEmpty()) {
return CdpDriver.start(options);
}
if (wsUrl.contains("/devtools/browser/")) {
return CdpDriver.connectNewContext(wsUrl, options);
}
if (poolSize > 1) {
logger.warn("pool size {} but webSocketUrl names a single page — all slots will drive the SAME tab."
+ " Pass a browser-level endpoint (see /json/version) for isolated slots: {}", poolSize, wsUrl);
}
return CdpDriver.connect(wsUrl, options);
}
private void closeDriverQuietly(Driver driver) {
try {
if (!driver.isTerminated()) {
driver.quit();
}
} catch (Exception e) {
logger.warn("Error closing driver: {}", e.getMessage());
}
}
/**
* Get current pool size (may be -1 if not yet initialized).
*/View on GitHub (pinned to a22eb90246)