karatelabs/karate · error · DriverException
browser did not return a targetId for context
Error message
browser did not return a targetId for context: {contextId} What it means
After successfully creating an owned browser context, Karate calls Target.createTarget (about:blank) inside it to get a page targetId. If the response has no targetId, Karate cannot derive the page WebSocket endpoint and throws this DriverException. The context creation succeeded, so the browser is talking CDP but refused or failed to create the page target.
Solutions
- Check the browser is still alive and not over target/process limits when connecting (kill -9'd or crashed browsers will fail here)
- Retry with fewer concurrent contexts or restart the browser
- Verify the browser version is compatible with the Karate version's CDP usage and upgrade either side
- Enable CDP debug logging to inspect the Target.createTarget response for the actual failure
Example fix
// before
CdpDriver.connectNewContext(wsUrl, options); // browser already saturated
// after
// ensure browser capacity, e.g. launch with higher limits
startChrome("--remote-debugging-port=9222 --max-active-web-contexts=50");
CdpDriver.connectNewContext(wsUrl, options); Defensive patterns
Strategy: retry
Validate before calling
// verify browser is responsive before connecting
String ver = Http.get("http://host:port/json/version");
if (ver == null || ver.isEmpty()) throw new IllegalStateException("browser debug endpoint not responding"); Try / catch
try { return CdpDriver.connectNewContext(wsUrl, options); } catch (DriverException e) { if (e.getMessage().contains("targetId")) { restartBrowser(); return retryConnect(wsUrl, options); } throw e; } Prevention
- Avoid saturating one browser with too many parallel contexts
- Monitor browser process health during long test runs
- Pin compatible browser versions in CI
- Retry transient connect failures once or twice
When it happens
Trigger: CdpDriver.connectNewContext when Target.createTarget with browserContextId returns no targetId — e.g. browser hit its max-targets limit, the context was already torn down, or the browser sends a malformed/empty CDP result.
Common situations: Running many parallel tests against one browser exhausting target limits; headless shell variants with restricted Target domains; the browser crashing or being killed mid-connect; corporate browser policies (e.g. Edge/Chrome enterprise) blocking target creation.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- browser did not return a browserContextId
- not a devtools websocket url
- failed to create blank tab, quitting driver
- CDP connection failed readiness check
- CDP timeout for
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/afbbebf8a10417ba.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:554
*
* @param browserWebSocketUrl a BROWSER-level endpoint (ws://host:port/devtools/browser/...),
* not a page endpoint — see /json/version
*/
public static CdpDriver connectNewContext(String browserWebSocketUrl, CdpDriverOptions options) {
CdpClient browser = CdpClient.connect(browserWebSocketUrl, options.getTimeoutDuration());
try {
String contextId = browser.browserMethod("Target.createBrowserContext")
.send().getResultAsString("browserContextId");
if (contextId == null) {
throw new DriverException("browser did not return a browserContextId: " + browserWebSocketUrl);
}
try {
String targetId = browser.browserMethod("Target.createTarget")
.param("url", "about:blank")
.param("browserContextId", contextId)
.send().getResultAsString("targetId");
if (targetId == null) {
throw new DriverException("browser did not return a targetId for context: " + contextId);
}
CdpDriver driver = new CdpDriver(pageWsUrlFrom(browserWebSocketUrl, targetId), options);
driver.ownedBrowserContextId = contextId;
driver.browserWebSocketUrl = browserWebSocketUrl;
logger.debug("created driver in browser context {} target {}", contextId, targetId);
return driver;
} catch (RuntimeException e) {
// Never leave an orphan context behind on a half-built driver — it would
// pin its storage partition for the life of the browser.
try {
browser.browserMethod("Target.disposeBrowserContext")
.param("browserContextId", contextId).send();
} catch (Exception ignored) {
logger.debug("could not dispose orphan browser context: {}", contextId);
}
throw e;
}
} finally {View on GitHub (pinned to a22eb90246)