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

  1. Check the browser is still alive and not over target/process limits when connecting (kill -9'd or crashed browsers will fail here)
  2. Retry with fewer concurrent contexts or restart the browser
  3. Verify the browser version is compatible with the Karate version's CDP usage and upgrade either side
  4. 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

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


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)