{"record":{"id":"2c5f0caa62c85d7b","repo":"karatelabs/karate","slug":"error-closing-driver-pooleddriverprovider","errorCode":null,"errorMessage":"Error closing driver: {}","messagePattern":"Error closing driver: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java","lineNumber":451,"sourceCode":"            return CdpDriver.start(options);\n        }\n        if (wsUrl.contains(\"/devtools/browser/\")) {\n            return CdpDriver.connectNewContext(wsUrl, options);\n        }\n        if (poolSize > 1) {\n            logger.warn(\"pool size {} but webSocketUrl names a single page — all slots will drive the SAME tab.\"\n                    + \" Pass a browser-level endpoint (see /json/version) for isolated slots: {}\", poolSize, wsUrl);\n        }\n        return CdpDriver.connect(wsUrl, options);\n    }\n\n    private void closeDriverQuietly(Driver driver) {\n        try {\n            if (!driver.isTerminated()) {\n                driver.quit();\n            }\n        } catch (Exception e) {\n            logger.warn(\"Error closing driver: {}\", e.getMessage());\n        }\n    }\n\n    /**\n     * Get current pool size (may be -1 if not yet initialized).\n     */\n    public int getPoolSize() {\n        return poolSize;\n    }\n\n    /**\n     * Get current pool statistics for monitoring.\n     */\n    public String getStats() {\n        return String.format(\"PooledDriverProvider[size=%d, created=%d, available=%d, assigned=%d]\",\n                poolSize, createdCount.get(),\n                availableDrivers != null ? availableDrivers.size() : 0,\n                assignedDrivers.size());","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java#L433-L469","documentation":"closeDriverQuietly() attempts driver.quit() (only if not already terminated) and swallows any exception, logging this warning with e.getMessage(). It is a best-effort cleanup used when discarding dead or excess drivers, so the warning indicates quit failed but execution continues.","triggerScenarios":"driver.quit() throwing during pool discard — e.g. websocket already closed, CDP call timing out on a crashed browser, or the process already gone so the quit RPC fails.","commonSituations":"Browser killed externally (OOM, SIGKILL) while pooled; CDP channel broken mid-teardown; zombie chrome process lingering after a failed quit.","solutions":["Check for leftover browser processes and clean them up (kill stale chrome between CI runs)","Verify the browser/CDP versions match the driver expectations","If the message is 'already closed' style, it is benign — filter or downgrade the log","Ensure process killing (driver.process kill) works on the platform; some CI containers need extra privileges"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if (!driver.isTerminated()) { /* safe to quit */ }","typeGuard":"boolean quittable = d -> d != null && !d.isTerminated();","tryCatchPattern":"try { if (!driver.isTerminated()) driver.quit(); } catch (Exception e) { /* already gone */ }","preventionTips":["Kill leftover chrome processes between CI runs","Match browser/CDP versions to the driver build","Ignore benign 'already closed' messages in log triage"],"tags":["driver-cleanup","cdp","browser-crash","shutdown"],"backgroundTag":"broken-pipe","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}