karatelabs/karate · error · IllegalArgumentException
pool sizes must be at least 1, got maxTotal= perRoute=
Error message
pool sizes must be at least 1, got maxTotal= perRoute=
What it means
KarateProtocolBuilder.pooledConnections(maxTotal, perRoute) sizes the HTTP connection pool. Both values must be at least 1; calling with zero or negative values throws IllegalArgumentException echoing both numbers. The builder also deliberately closes any previously registered pool when called again, so call it at most once per builder.
Solutions
- Pass positive integers for both, e.g. pooledConnections(200, 20)
- Ensure the config feeding these numbers has sane non-zero defaults
- For single-endpoint tests set perRoute equal to maxTotal (the binding number)
- Call pooledConnections only once per builder — later calls abandon (and close) the earlier pool
Example fix
// before
int total = Integer.getInteger("pool.total", 0);
protocol.pooledConnections(total, total / 4); // 0/4 -> perRoute=0
// after
int total = Integer.getInteger("pool.total", 200);
protocol.pooledConnections(total, Math.max(1, total / 4)); Defensive patterns
Strategy: validation
Validate before calling
if (maxTotal < 1 || perRoute < 1) { throw new IllegalArgumentException("pool sizes must be >= 1"); } Try / catch
try {
protocol.pooledConnections(maxTotal, perRoute);
} catch (IllegalArgumentException e) {
protocol.pooledConnections(200, 20);
} Prevention
- Default both values to >= 1 when reading from config
- For single-endpoint tests set perRoute == maxTotal
- Call pooledConnections exactly once per builder to avoid abandoning pools
- Avoid integer division that can yield 0 for small inputs
When it happens
Trigger: Calling pooledConnections(0, x), pooledConnections(x, 0), or with negative values — often from config defaults of 0 or math like total/concurrency evaluating to 0.
Common situations: Unset system property parsed to 0; division producing 0 for tiny concurrency; misunderstanding that perRoute should be 0 for 'no per-route limit' (it must be >= 1).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- feature path is required
- invalid log replay mode: '', expected one of: off, failed…
- invalid log replay level: '', expected one of: trace…
- logReplayLimit must be at least 1, was: (use…
- http method expression evaluated to null:
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/7a133e28972db06f.
Report an issue: GitHub.
Appendix: source
Thrown at karate-gatling/src/main/java/io/karatelabs/gatling/KarateProtocolBuilder.java:195
public KarateProtocolBuilder pooledConnections() {
return pooledConnections(PooledHttpClientFactory.DEFAULT_MAX_CONNECTIONS,
PooledHttpClientFactory.DEFAULT_MAX_CONNECTIONS);
}
/**
* As {@link #pooledConnections()}, with an explicit ceiling.
*
* <p>Size it above the peak virtual-user count. The pool opens connections on demand, so a high
* ceiling costs nothing, while one below the concurrency becomes a bottleneck that reads as the
* server being slow rather than as a client limit.
*
* @param maxTotal total pooled connections across all routes
* @param perRoute connections per target host — the binding number for a single-endpoint test
* @return this builder for chaining
*/
public KarateProtocolBuilder pooledConnections(int maxTotal, int perRoute) {
if (maxTotal < 1 || perRoute < 1) {
throw new IllegalArgumentException("pool sizes must be at least 1, got maxTotal="
+ maxTotal + " perRoute=" + perRoute);
}
// Calling this twice used to overwrite the field and abandon the first pool: only the last
// one reaches the protocol, so only the last one is ever registered for close, and the
// other's connection manager survives the simulation holding whatever it had opened.
// Closing here is safe because nothing has leased from it yet — the protocol has not been
// built, so no scenario has a client.
if (pool != null) {
pool.close();
}
pool = new PooledHttpClientFactory(maxTotal, perRoute);
runner.httpClientFactory(pool);
return this;
}
/**
* Build the KarateProtocol.
*/View on GitHub (pinned to a22eb90246)