karatelabs/karate · warning
Pool exhausted for scenario
Error message
Pool exhausted for scenario '{}', waiting for available driver... [{}] What it means
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.
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
Example fix
// before -Dkarate.options="-t @smoke threads=10" // driver.poolSize defaults lower // after DriverOptions options = ...; options.setPoolSize(10); // or set -Ddriver.poolSize=10 so each thread gets a slot
Defensive patterns
Strategy: validation
Validate before calling
// before the run: ensure pool >= threads
int threads = Integer.getInteger("karate.threads", 1);
int pool = Integer.getInteger("driver.poolSize", threads);
if (pool < threads) throw new IllegalStateException(
"driver.poolSize (" + pool + ") must be >= parallel threads (" + threads + ")"); Try / catch
try {
Driver d = provider.acquire(options, runtime);
} catch (RuntimeException e) {
if (e.getMessage().contains("Timeout waiting for available driver")) {
// retry once or fail the scenario fast
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- Timeout waiting for available driver for scenario
- timed out waiting for promise
- Timeout waiting for Karate test events after
- Pool full, closing excess driver
- HTTP endpoint not available
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/d6a3001ac7d57911.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java:195
return;
}
// Auto-detect pool size from Suite's threadCount
if (poolSize < 1 && runtime.getFeatureRuntime() != null
&& runtime.getFeatureRuntime().getSuite() != null) {
poolSize = runtime.getFeatureRuntime().getSuite().threadCount;
logger.info("Auto-detected pool size from Suite: {}", poolSize);
}
if (poolSize < 1) {
poolSize = 1; // Fallback
logger.warn("Could not detect pool size, defaulting to 1");
}
availableDrivers = new ArrayBlockingQueue<>(poolSize);
}
}
private Driver waitForDriver(Map<String, Object> config, ScenarioRuntime runtime) {
String scenarioName = runtime.getScenario().getName();
logger.warn("Pool exhausted for scenario '{}', waiting for available driver... [{}]",
scenarioName, getStats());
try {
Driver driver = availableDrivers.poll(30, TimeUnit.SECONDS);
if (driver == null) {
throw new RuntimeException("Timeout waiting for available driver for scenario '"
+ scenarioName + "' [" + getStats() + "]");
}
// If the driver is terminated OR fails reset/liveness, replace it.
// Same rationale as takeHealthyFromPool — a poisoned driver must not be
// handed out to the next scenario.
if (driver.isTerminated()) {
createdCount.decrementAndGet();
driver = createDriver(config);
createdCount.incrementAndGet();
logger.info("Replaced terminated driver for scenario: {}", scenarioName);
} else if (!resetDriver(driver)) {
closeDriverQuietly(driver);
createdCount.decrementAndGet();View on GitHub (pinned to a22eb90246)