{"record":{"id":"d6a3001ac7d57911","repo":"karatelabs/karate","slug":"pool-exhausted-for-scenario-waiting-for-available-driver","errorCode":null,"errorMessage":"Pool exhausted for scenario '{}', waiting for available driver... [{}]","messagePattern":"Pool exhausted for scenario '(.+?)', waiting for available driver\\.\\.\\. \\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java","lineNumber":195,"sourceCode":"                return;\n            }\n            // Auto-detect pool size from Suite's threadCount\n            if (poolSize < 1 && runtime.getFeatureRuntime() != null\n                    && runtime.getFeatureRuntime().getSuite() != null) {\n                poolSize = runtime.getFeatureRuntime().getSuite().threadCount;\n                logger.info(\"Auto-detected pool size from Suite: {}\", poolSize);\n            }\n            if (poolSize < 1) {\n                poolSize = 1;  // Fallback\n                logger.warn(\"Could not detect pool size, defaulting to 1\");\n            }\n            availableDrivers = new ArrayBlockingQueue<>(poolSize);\n        }\n    }\n\n    private Driver waitForDriver(Map<String, Object> config, ScenarioRuntime runtime) {\n        String scenarioName = runtime.getScenario().getName();\n        logger.warn(\"Pool exhausted for scenario '{}', waiting for available driver... [{}]\",\n                scenarioName, getStats());\n        try {\n            Driver driver = availableDrivers.poll(30, TimeUnit.SECONDS);\n            if (driver == null) {\n                throw new RuntimeException(\"Timeout waiting for available driver for scenario '\"\n                        + scenarioName + \"' [\" + getStats() + \"]\");\n            }\n            // If the driver is terminated OR fails reset/liveness, replace it.\n            // Same rationale as takeHealthyFromPool — a poisoned driver must not be\n            // handed out to the next scenario.\n            if (driver.isTerminated()) {\n                createdCount.decrementAndGet();\n                driver = createDriver(config);\n                createdCount.incrementAndGet();\n                logger.info(\"Replaced terminated driver for scenario: {}\", scenarioName);\n            } else if (!resetDriver(driver)) {\n                closeDriverQuietly(driver);\n                createdCount.decrementAndGet();","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java#L177-L213","documentation":"PooledDriverProvider logs this warning when all drivers in the fixed-size pool are busy and a new scenario must wait up to 30 seconds for one to be released. If no driver is returned within the timeout, a RuntimeException ('Timeout waiting for available driver') is thrown. It signals that demand for browser drivers exceeds the configured pool size.","triggerScenarios":"Running more concurrent scenarios than the configured karate driver pool size; a scenario leaking/not releasing drivers so acquire() calls waitForDriver() with every slot taken.","commonSituations":"CI parallel runs where parallel count exceeds poolSize; a stuck scenario holding a driver past 30s (hangs on navigation); forgetting to size the pool to match threads in karate.options.","solutions":["Increase the driver pool size (driver.poolSize / karate.pool config) to at least the parallel scenario count","Fix scenarios that hang and hold drivers (add navigation timeouts, fail fast)","Reduce parallelism (-Dkarate.options='... threads=...') to match pool size","Check pool stats in the log ([{}]) to see how many drivers are created vs waiting"],"exampleFix":"// before\n-Dkarate.options=\"-t @smoke threads=10\"\n// driver.poolSize defaults lower\n// after\nDriverOptions options = ...; options.setPoolSize(10);\n// or set -Ddriver.poolSize=10 so each thread gets a slot","handlingStrategy":"validation","validationCode":"// before the run: ensure pool >= threads\nint threads = Integer.getInteger(\"karate.threads\", 1);\nint pool = Integer.getInteger(\"driver.poolSize\", threads);\nif (pool < threads) throw new IllegalStateException(\n    \"driver.poolSize (\" + pool + \") must be >= parallel threads (\" + threads + \")\");","typeGuard":null,"tryCatchPattern":"try {\n    Driver d = provider.acquire(options, runtime);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"Timeout waiting for available driver\")) {\n        // retry once or fail the scenario fast\n    }\n}","preventionTips":["Set poolSize >= parallel thread count before CI runs","Watch for 'Pool exhausted' warnings early in a run — they predict later timeouts","Avoid scenarios that hang on navigation; bound waits with timeouts"],"tags":["driver-pool","browser-automation","concurrency","timeout"],"backgroundTag":"request-timeout","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"}