{"record":{"id":"7a133e28972db06f","repo":"karatelabs/karate","slug":"pool-sizes-must-be-at-least-1-got-maxtotal-perroute","errorCode":null,"errorMessage":"pool sizes must be at least 1, got maxTotal= perRoute=","messagePattern":"pool sizes must be at least 1, got maxTotal= perRoute=","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"karate-gatling/src/main/java/io/karatelabs/gatling/KarateProtocolBuilder.java","lineNumber":195,"sourceCode":"    public KarateProtocolBuilder pooledConnections() {\n        return pooledConnections(PooledHttpClientFactory.DEFAULT_MAX_CONNECTIONS,\n                PooledHttpClientFactory.DEFAULT_MAX_CONNECTIONS);\n    }\n\n    /**\n     * As {@link #pooledConnections()}, with an explicit ceiling.\n     *\n     * <p>Size it above the peak virtual-user count. The pool opens connections on demand, so a high\n     * ceiling costs nothing, while one below the concurrency becomes a bottleneck that reads as the\n     * server being slow rather than as a client limit.\n     *\n     * @param maxTotal total pooled connections across all routes\n     * @param perRoute connections per target host — the binding number for a single-endpoint test\n     * @return this builder for chaining\n     */\n    public KarateProtocolBuilder pooledConnections(int maxTotal, int perRoute) {\n        if (maxTotal < 1 || perRoute < 1) {\n            throw new IllegalArgumentException(\"pool sizes must be at least 1, got maxTotal=\"\n                    + maxTotal + \" perRoute=\" + perRoute);\n        }\n        // Calling this twice used to overwrite the field and abandon the first pool: only the last\n        // one reaches the protocol, so only the last one is ever registered for close, and the\n        // other's connection manager survives the simulation holding whatever it had opened.\n        // Closing here is safe because nothing has leased from it yet — the protocol has not been\n        // built, so no scenario has a client.\n        if (pool != null) {\n            pool.close();\n        }\n        pool = new PooledHttpClientFactory(maxTotal, perRoute);\n        runner.httpClientFactory(pool);\n        return this;\n    }\n\n    /**\n     * Build the KarateProtocol.\n     */","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-gatling/src/main/java/io/karatelabs/gatling/KarateProtocolBuilder.java#L177-L213","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"// before\nint total = Integer.getInteger(\"pool.total\", 0);\nprotocol.pooledConnections(total, total / 4); // 0/4 -> perRoute=0\n// after\nint total = Integer.getInteger(\"pool.total\", 200);\nprotocol.pooledConnections(total, Math.max(1, total / 4));","handlingStrategy":"validation","validationCode":"if (maxTotal < 1 || perRoute < 1) { throw new IllegalArgumentException(\"pool sizes must be >= 1\"); }","typeGuard":null,"tryCatchPattern":"try {\n  protocol.pooledConnections(maxTotal, perRoute);\n} catch (IllegalArgumentException e) {\n  protocol.pooledConnections(200, 20);\n}","preventionTips":["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"],"tags":["gatling","karate","http","connection-pool","configuration"],"backgroundTag":"value-out-of-range","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"}