{"record":{"id":"c2e5254008a30b09","repo":"apache/pulsar","slug":"iothreads-must-be-1","errorCode":null,"errorMessage":"ioThreads must be >= 1","messagePattern":"ioThreads must be >= 1","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/ConnectionPolicy.java","lineNumber":67,"sourceCode":"    private ConnectionPolicy(Duration connectionTimeout,\n                             int connectionsPerBroker,\n                             boolean enableTcpNoDelay,\n                             Duration keepAliveInterval,\n                             Duration connectionMaxIdleTime,\n                             int ioThreads,\n                             int callbackThreads,\n                             String proxyServiceUrl,\n                             ProxyProtocol proxyProtocol,\n                             BackoffPolicy connectionBackoff) {\n        Objects.requireNonNull(connectionTimeout, \"connectionTimeout must not be null\");\n        Objects.requireNonNull(keepAliveInterval, \"keepAliveInterval must not be null\");\n        Objects.requireNonNull(connectionMaxIdleTime, \"connectionMaxIdleTime must not be null\");\n        Objects.requireNonNull(connectionBackoff, \"connectionBackoff must not be null\");\n        if (connectionsPerBroker < 1) {\n            throw new IllegalArgumentException(\"connectionsPerBroker must be >= 1\");\n        }\n        if (ioThreads < 1) {\n            throw new IllegalArgumentException(\"ioThreads must be >= 1\");\n        }\n        if (callbackThreads < 1) {\n            throw new IllegalArgumentException(\"callbackThreads must be >= 1\");\n        }\n        this.connectionTimeout = connectionTimeout;\n        this.connectionsPerBroker = connectionsPerBroker;\n        this.enableTcpNoDelay = enableTcpNoDelay;\n        this.keepAliveInterval = keepAliveInterval;\n        this.connectionMaxIdleTime = connectionMaxIdleTime;\n        this.ioThreads = ioThreads;\n        this.callbackThreads = callbackThreads;\n        this.proxyServiceUrl = proxyServiceUrl;\n        this.proxyProtocol = proxyProtocol;\n        this.connectionBackoff = connectionBackoff;\n    }\n\n    /**\n     * @return the maximum duration to wait for a TCP connection to a broker","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/ConnectionPolicy.java#L49-L85","documentation":"ConnectionPolicy requires ioThreads >= 1 because ioThreads sets the number of Netty event-loop threads handling the client's network I/O; zero or negative thread counts would make the client unable to process socket events. The constructor throws IllegalArgumentException for smaller values.","triggerScenarios":"Calling ConnectionPolicy.builder().ioThreads(0) or a negative value; sizing ioThreads from available processors with a formula that returns 0 (e.g. Runtime.getRuntime().availableProcessors() / N when N exceeds core count).","commonSituations":"Container CPU limits making availableProcessors() small, so a division-based sizing formula yields 0; using 0 as a 'default' sentinel; config parsing an empty value into 0.","solutions":["Set ioThreads to at least 1 (a common choice is the number of CPU cores).","Clamp computed values: Math.max(1, Runtime.getRuntime().availableProcessors() / 2).","Omit the ioThreads call to use the library default."],"exampleFix":"// before\nint threads = Runtime.getRuntime().availableProcessors() / 8; // 0 on a 4-core box\nConnectionPolicy cp = ConnectionPolicy.builder()\n    .ioThreads(threads) // IllegalArgumentException\n    .build();\n\n// after\nint threads = Math.max(1, Runtime.getRuntime().availableProcessors() / 8);\nConnectionPolicy cp = ConnectionPolicy.builder()\n    .ioThreads(threads)\n    .build();","handlingStrategy":"validation","validationCode":"int threads = Math.max(1, cfg.ioThreads() > 0 ? cfg.ioThreads() : Runtime.getRuntime().availableProcessors());\nConnectionPolicy cp = ConnectionPolicy.builder().ioThreads(threads).build();","typeGuard":"static boolean isValidIoThreads(int v) { return v >= 1; }","tryCatchPattern":"try {\n    cp = ConnectionPolicy.builder().ioThreads(threads).build();\n} catch (IllegalArgumentException e) {\n    log.warn(\"Invalid ioThreads, using default\", e);\n    cp = ConnectionPolicy.builder().build();\n}","preventionTips":["Clamp CPU-derived sizing formulas: Math.max(1, cpus / divisor).","Account for container CPU limits making availableProcessors() small.","Validate thread counts alongside each other (ioThreads, callbackThreads) at startup."],"tags":["java","configuration","threading","io","illegal-argument"],"backgroundTag":"invalid-configuration-value","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}