{"id":"2c7913d70acaf8f6","repo":"apache/kafka","slug":"more-frequencies-than-buckets","errorCode":null,"errorMessage":"More frequencies than buckets","messagePattern":"More frequencies than buckets","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java","lineNumber":97,"sourceCode":"     * @param min         the minimum value to be captured\n     * @param max         the maximum value to be captured\n     * @param frequencies the list of {@link Frequency} metrics, which at most should be one per bucket centered\n     *                    on the bucket's value, though not every bucket need to correspond to a metric if the\n     *                    value is not needed\n     * @throws IllegalArgumentException if any of the {@link Frequency} objects do not have a\n     *                                  {@link Frequency#centerValue() center value} within the specified range\n     */\n    public Frequencies(int buckets, double min, double max, Frequency... frequencies) {\n        super(0.0); // initial value is unused by this implementation\n        if (max < min) {\n            throw new IllegalArgumentException(\"The maximum value \" + max\n                                                       + \" must be greater than the minimum value \" + min);\n        }\n        if (buckets < 1) {\n            throw new IllegalArgumentException(\"Must be at least 1 bucket\");\n        }\n        if (buckets < frequencies.length) {\n            throw new IllegalArgumentException(\"More frequencies than buckets\");\n        }\n        this.frequencies = frequencies;\n        for (Frequency freq : frequencies) {\n            if (min > freq.centerValue() || max < freq.centerValue()) {\n                throw new IllegalArgumentException(\"The frequency centered at '\" + freq.centerValue()\n                                                           + \"' is not within the range [\" + min + \",\" + max + \"]\");\n            }\n        }\n        double halfBucketWidth = (max - min) / (buckets - 1) / 2.0;\n        this.binScheme = new ConstantBinScheme(buckets, min - halfBucketWidth, max + halfBucketWidth);\n    }\n\n    @Override\n    public List<NamedMeasurable> stats() {\n        List<NamedMeasurable> ms = new ArrayList<>(frequencies.length);\n        for (Frequency frequency : frequencies) {\n            final double center = frequency.centerValue();\n            ms.add(new NamedMeasurable(frequency.name(), (config, now) -> frequency(config, now, center)));","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java#L79-L115","documentation":"Thrown by the Frequencies constructor when the number of Frequency metrics supplied exceeds the number of buckets. Each Frequency reports the count in the bucket centered on its centerValue, so you cannot meaningfully track more centered values than there are bins — at most one Frequency per bucket is the contract documented at line 81-83. The check enforces buckets >= frequencies.length.","triggerScenarios":"Calling new Frequencies(buckets, min, max, freqs) with more Frequency entries than buckets — e.g. new Frequencies(2, 0, 1, f1, f2, f3). Happens when the bucket count is fixed (or computed independently) and does not account for how many distinct centerValues the caller wants to track.","commonSituations":"Boolean use that tracks 3+ outcomes but passes buckets=2; mismatch between a configured bucket count and a hard-coded list of Frequency metrics; refactoring that added a Frequency without raising the bucket count.","solutions":["Raise buckets to at least the number of Frequency objects you pass.","Reduce the number of Frequency metrics so it fits within the bucket count.","Use Frequencies.forBooleanValues(...) for the common true/false case — it sets buckets=2 and supplies exactly two frequencies."],"exampleFix":"// before\nnew Frequencies(2, 0.0, 10.0,\n    new Frequency(low, 0.0), new Frequency(mid, 5.0), new Frequency(high, 10.0)); // 3 freqs, 2 buckets\n// after\nnew Frequencies(3, 0.0, 10.0,\n    new Frequency(low, 0.0), new Frequency(mid, 5.0), new Frequency(high, 10.0));","handlingStrategy":"validation","validationCode":"// Ensure the bucket count can hold every Frequency you pass:\nif (frequencies == null) frequencies = new Frequency[0];\nif (buckets < frequencies.length) {\n    throw new IllegalArgumentException(\n        \"Need at least \" + frequencies.length + \" buckets for \" + frequencies.length + \" frequencies, got \" + buckets);\n}\nreturn new Frequencies(buckets, min, max, frequencies);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Size buckets to at least the number of distinct Frequency centers you define.","For boolean distributions prefer Frequencies.forBooleanValues, which fixes buckets=2 and min=0/max=1 for you.","When configuring buckets from user input, validate against the configured frequency list at parse time."],"tags":["metrics","validation","histogram"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}