{"record":{"id":"404f62e3a524e02b","repo":"karatelabs/karate","slug":"browser-did-not-return-a-browsercontextid","errorCode":null,"errorMessage":"browser did not return a browserContextId: {browserWebSocketUrl}","messagePattern":"browser did not return a browserContextId: (.+?)","errorType":"exception","errorClass":"DriverException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":546,"sourceCode":"     * cookies of every other scenario running concurrently in that context. Per-tab\n     * clearing cannot fix that; there is only one jar to clear. A per-driver context\n     * gives each driver its own jar, so the reset only ever affects its own scenario.\n     * </p>\n     * <p>\n     * The returned driver owns the context and disposes it (closing its tab with it) on\n     * {@link #quit()}.\n     * </p>\n     *\n     * @param browserWebSocketUrl a BROWSER-level endpoint (ws://host:port/devtools/browser/...),\n     *                            not a page endpoint — see /json/version\n     */\n    public static CdpDriver connectNewContext(String browserWebSocketUrl, CdpDriverOptions options) {\n        CdpClient browser = CdpClient.connect(browserWebSocketUrl, options.getTimeoutDuration());\n        try {\n            String contextId = browser.browserMethod(\"Target.createBrowserContext\")\n                    .send().getResultAsString(\"browserContextId\");\n            if (contextId == null) {\n                throw new DriverException(\"browser did not return a browserContextId: \" + browserWebSocketUrl);\n            }\n            try {\n                String targetId = browser.browserMethod(\"Target.createTarget\")\n                        .param(\"url\", \"about:blank\")\n                        .param(\"browserContextId\", contextId)\n                        .send().getResultAsString(\"targetId\");\n                if (targetId == null) {\n                    throw new DriverException(\"browser did not return a targetId for context: \" + contextId);\n                }\n                CdpDriver driver = new CdpDriver(pageWsUrlFrom(browserWebSocketUrl, targetId), options);\n                driver.ownedBrowserContextId = contextId;\n                driver.browserWebSocketUrl = browserWebSocketUrl;\n                logger.debug(\"created driver in browser context {} target {}\", contextId, targetId);\n                return driver;\n            } catch (RuntimeException e) {\n                // Never leave an orphan context behind on a half-built driver — it would\n                // pin its storage partition for the life of the browser.\n                try {","sourceCodeStart":528,"sourceCodeEnd":564,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L528-L564","documentation":"When Karate attaches to an already-running browser via its WebSocket URL, it first asks the browser to create a new incognito-like browser context (Target.createBrowserContext). If the CDP response contains no browserContextId, Karate cannot proceed to create a target/page inside it, so it throws this DriverException. It indicates the browser responded but not with the expected CDP payload.","triggerScenarios":"Calling CdpDriver.connectNewContext(browserWebSocketUrl, options) against a browser whose response to Target.createBrowserContext lacks a browserContextId — typically a non-Chrome/CDP-compatible endpoint, a proxy mangling the response, or a browser whose CDP protocol version differs from what Karate expects.","commonSituations":"Pointing Karate at a WebSocket URL that is not really a Chromium devtools endpoint (e.g. an Electron app, old Chromium build, or a CDP-proxy like chrome-remote-interface relays); browser upgrades changing CDP response shapes; connecting to a websocket that speaks a similar but not identical protocol.","solutions":["Verify the browserWebSocketUrl is a genuine Chromium/Chrome devtools browser endpoint (ws://host:port/devtools/browser/<id>) from a recent Chrome/Chromium/Edge build","Launch the browser with --remote-debugging-port and take the URL from http://host:port/json/version (webSocketDebuggerUrl) rather than hand-crafting it","Upgrade karate to a version matching your browser's CDP protocol version","Capture CDP traffic (e.g. with a logging proxy) to inspect the Target.createBrowserContext response for a missing browserContextId"],"exampleFix":"// before\nCdpDriver.connectNewContext(\"ws://localhost:9222/devtools/browser/guess\", options);\n// after\nString wsUrl = new Json(IoUtils.fromCdpUrl(\"localhost\", 9222)).get(\"webSocketDebuggerUrl\");\nCdpDriver.connectNewContext(wsUrl, options);","handlingStrategy":"validation","validationCode":"if (!browserWebSocketUrl.matches(\"ws(s)?://[^/]+/devtools/browser/.+\")) throw new IllegalArgumentException(\"expected devtools browser ws url, got: \" + browserWebSocketUrl);","typeGuard":null,"tryCatchPattern":"try { driver = CdpDriver.connectNewContext(wsUrl, options); } catch (DriverException e) { if (e.getMessage().contains(\"browserContextId\")) { /* fall back to plain connect or restart browser */ } else throw e; }","preventionTips":["Fetch the ws URL from http://host:port/json/version webSocketDebuggerUrl instead of constructing it","Use a current Chrome/Chromium/Edge build for the driver","Keep Karate and browser versions aligned","Smoke-test the endpoint with curl http://host:port/json before running tests"],"tags":["cdp","browser-automation","websocket"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}