{"record":{"id":"d34f5c6e9e39cd17","repo":"karatelabs/karate","slug":"currenttargetid-fallback-to-getpages-0-parallel-execution","errorCode":null,"errorMessage":"currentTargetId fallback to getPages()[0]: {} - parallel execution may be unreliable","messagePattern":"currentTargetId fallback to getPages\\(\\)\\[0\\]: (.+?) - parallel execution may be unreliable","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":617,"sourceCode":"        // CRITICAL: Get main frame ID FIRST - needed by event handlers\n        // This works without Page.enable and ensures handlers can filter by frame\n        CdpResponse frameResponse = cdp.method(\"Page.getFrameTree\").send();\n        mainFrameId = frameResponse.getResult(\"frameTree.frame.id\");\n        // Seed the committed-document tracker so the first setUrl's readyState\n        // fallback can already tell the pre-existing document from the requested one.\n        committedLoaderId = frameResponse.getResultAsString(\"frameTree.frame.loaderId\");\n        logger.debug(\"main frame ID: {}\", mainFrameId);\n\n        // Track current target for close() support\n        // currentTargetId is set in constructor by extracting from WebSocket URL (preferred)\n        // Fallback: if URL extraction failed (e.g., browser-level URL), use getPages()\n        // Note: getPages() fallback is NOT safe for parallel execution - all drivers would\n        // get the same targetId. This is only for backwards compatibility with browser-level connections.\n        if (currentTargetId == null) {\n            List<String> pages = getPages();\n            if (!pages.isEmpty()) {\n                currentTargetId = pages.get(0);\n                logger.warn(\"currentTargetId fallback to getPages()[0]: {} - parallel execution may be unreliable\", currentTargetId);\n            }\n        } else {\n            logger.debug(\"current target ID (from URL): {}\", currentTargetId);\n        }\n\n        // Resolve which browser context our tab lives in, so tab enumeration can be scoped\n        // to it. Done by lookup rather than trusting ownedBrowserContextId: a driver that\n        // merely connected to a page did not create that page's context but still must not\n        // enumerate across into someone else's.\n        browserContextId = lookupBrowserContextId(currentTargetId);\n        logger.debug(\"browser context ID: {}\", browserContextId == null ? \"<default>\" : browserContextId);\n\n        // Setup event handlers BEFORE enabling domains\n        // This prevents race conditions where events fire before handlers are registered\n        setupEventHandlers();\n\n        // Record the main page's session id BEFORE enabling domains so the Page.*\n        // session filter has a reference value for the first wave of events.","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L599-L635","documentation":"During CdpDriver.initialize(), if no targetId could be derived from the connection URL, the driver falls back to getPages()[0] and warns that this is not safe for parallel execution — all fallback drivers would attach to the same first tab. It exists only for backwards compatibility with browser-level connections that expose no target id in the URL.","triggerScenarios":"Connecting via CDP where the websocket URL does not embed a target id (older browser endpoint or custom proxy), so currentTargetId is null at initialize() time.","commonSituations":"Using a browser-level /devtools/browser/ URL with an older Chrome that does not auto-assign targets; custom DevTools proxies stripping target ids; connecting to an already-open Chrome with multiple tabs open.","solutions":["Connect with a URL that carries a target id, or use CdpDriver.connectNewContext() for browser-level endpoints so a fresh target is created","Close extra tabs before connecting so getPages()[0] is the intended one","Upgrade Chrome — newer builds provide per-target ws endpoints via /json/version","For parallel runs, always ensure each driver gets its own target instead of relying on the fallback"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"String ws = options.getWebSocketUrl();\nif (ws != null && ws.contains(\"/devtools/browser/\") && runningParallel) {\n    // require connectNewContext path so each driver has its own targetId\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For parallel CDP work, always use browser-level endpoint + connectNewContext","Close stray tabs before connecting to an existing Chrome","Upgrade Chrome to builds exposing per-target ws endpoints"],"tags":["cdp","targetid","parallel-execution","fallback"],"backgroundTag":"invalid-config-value","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"}