{"record":{"id":"c37948f136a86855","repo":"karatelabs/karate","slug":"timeout-waiting-for-target-to-be-removed","errorCode":null,"errorMessage":"timeout waiting for target to be removed: {}","messagePattern":"timeout waiting for target to be removed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":2802,"sourceCode":"    /**\n     * Wait for a closed target to actually disappear, event-driven: the future is\n     * completed by the Target.targetDestroyed handler. That event's delivery depends\n     * on Target.setDiscoverTargets, which initialize() arms best-effort — so on\n     * timeout, fall back to ONE page-list check before declaring a problem.\n     */\n    private void waitForTargetRemoved(String targetId, CompletableFuture<Void> removed) {\n        try {\n            removed.get(1000, TimeUnit.MILLISECONDS);\n            logger.trace(\"target removal confirmed by event: {}\", targetId);\n            return;\n        } catch (Exception e) {\n            // fall through to the direct check\n        }\n        if (!getPages().contains(targetId)) {\n            logger.trace(\"target removed from page list: {}\", targetId);\n            return;\n        }\n        logger.warn(\"timeout waiting for target to be removed: {}\", targetId);\n    }\n\n    public boolean isTerminated() {\n        return terminated;\n    }\n\n    @Override\n    public boolean isReady() {\n        CompletableFuture<Integer> f = mainContextReady;\n        return f.isDone() && !f.isCompletedExceptionally();\n    }\n\n    @Override\n    public void waitUntilReady() {\n        // The main frame execution context being live is the authoritative readiness\n        // signal (see mainContextReady). Block on it up to the configured timeout;\n        // returns immediately when already ready.\n        awaitMainContext(options.getTimeoutDuration().toMillis());","sourceCodeStart":2784,"sourceCodeEnd":2820,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L2784-L2820","documentation":"After closing a tab, CdpDriver waits for Target.targetDestroyed (or the page list to shrink) and falls back to a direct getPages() check. If the target still appears present after the wait, this warning is logged — the target removal event never arrived. Usually benign if the target did go away but the event/page list lagged; concerning if the tab genuinely failed to close.","triggerScenarios":"close() of a tab where Target.targetDestroyed wasn't observed within the wait window, slow CDP event delivery under load, beforeunload handlers blocking close, or a hung renderer keeping the target alive.","commonSituations":"Closing tabs with beforeunload dialogs, heavily loaded CI machines delaying CDP events, pages with long-running JS blocking teardown, or browser builds with delayed target cleanup.","solutions":["Ignore if the tab is actually gone — this is a warning, not an error; verify with driver.getPages().","Remove beforeunload handlers in the page before closing tabs.","If targets genuinely leak, close the whole browser (quit) instead of individual tabs.","Check CDP/websocket health and browser version; upgrade if event delivery is chronically delayed."],"exampleFix":"// before\ndriver.close(); // closes current tab, may warn\n// after\ndriver.script(\"window\", \"window.onbeforeunload = null\");\ndriver.close();","handlingStrategy":"fallback","validationCode":"// remove beforeunload before closing tabs\ndriver.script(\"window\", \"window.onbeforeunload = null\");","typeGuard":null,"tryCatchPattern":"try {\n    driver.close();\n} catch (RuntimeException e) {\n    // if the target genuinely leaked, tear down the whole browser\n    if (!driver.isTerminated()) { driver.quit(); }\n}","preventionTips":["Clear beforeunload handlers before tab close","Prefer quitting the whole browser when closing many tabs","Verify with getPages() whether the target truly leaked","Keep browser builds current to avoid event-delivery delays"],"tags":["cdp","target-lifecycle","event-delay","close"],"backgroundTag":"browser-cdp-session-failure","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"}