{"record":{"id":"ade0dba60928968d","repo":"apache/seatunnel","slug":"bucketcount-must-be-greater-than-zero-but-was-b","errorCode":null,"errorMessage":"bucketCount must be greater than zero, but was ${bucketCount}","messagePattern":"bucketCount must be greater than zero, but was (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-common/src/main/java/org/apache/seatunnel/common/utils/HashUtils.java","lineNumber":75,"sourceCode":"     * {@code int} because it is smaller than {@code bucketCount}.\n     *\n     * <p>This is a distinct mapping from the {@code int} overload rather than a widening of it: a\n     * 64-bit hash and its truncation to 32 bits generally land in different buckets, so a call site\n     * must not be switched between the two overloads.\n     *\n     * @param hash any 64-bit hash, including negative values and {@link Long#MIN_VALUE}\n     * @param bucketCount the number of buckets, must be greater than zero\n     * @return a bucket index in {@code [0, bucketCount)}\n     * @throws IllegalArgumentException if {@code bucketCount} is not greater than zero\n     */\n    public static int bucketIndex(long hash, int bucketCount) {\n        checkBucketCount(bucketCount);\n        return (int) ((hash & Long.MAX_VALUE) % bucketCount);\n    }\n\n    private static void checkBucketCount(int bucketCount) {\n        if (bucketCount <= 0) {\n            throw new IllegalArgumentException(\n                    \"bucketCount must be greater than zero, but was \" + bucketCount);\n        }\n    }\n}\n","sourceCodeStart":57,"sourceCodeEnd":80,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-common/src/main/java/org/apache/seatunnel/common/utils/HashUtils.java#L57-L80","documentation":"HashUtils.checkBucketCount validates that a bucket count is strictly positive before computing a bucket index via modulo. A count <= 0 throws IllegalArgumentException with the offending value, since modulo by zero or negative buckets is meaningless.","triggerScenarios":"Calling HashUtils.bucketIndex(...) (or checkBucketCount directly) with bucketCount <= 0 — e.g. a config option like bucket count resolved to 0 by a misparsed/empty config value.","commonSituations":"Connector config where the bucket/parallelism option was computed as 0 (e.g. an empty list size or a division result) and passed into hashing; off-by-one in code computing bucket count dynamically.","solutions":["Ensure bucketCount is at least 1 before calling bucketIndex (e.g. Math.max(1, configuredCount))","Fix the upstream computation/config that produced 0 or a negative value","If derived from a config option, add a validation rule that rejects values < 1 at option-parsing time"],"exampleFix":"// before\nint idx = HashUtils.bucketIndex(hash, bucketCount); // bucketCount may be 0\n// after\nint idx = HashUtils.bucketIndex(hash, Math.max(1, bucketCount));","handlingStrategy":"validation","validationCode":"if (bucketCount <= 0) throw new IllegalArgumentException(\"bucketCount must be >= 1, got \" + bucketCount);","typeGuard":"static int safeBucketCount(int n) { return Math.max(1, n); }","tryCatchPattern":"try { return HashUtils.bucketIndex(hash, bucketCount); } catch (IllegalArgumentException e) { return HashUtils.bucketIndex(hash, 1); }","preventionTips":["Clamp configured bucket counts with Math.max(1, value)","Validate bucket/parallelism options at config parse time","Check upstream computations that can yield 0 (empty lists, division)"],"tags":["hashing","argument-validation","range-check"],"backgroundTag":"value-out-of-range","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}