{"id":"7d4e5717ea45bc4f","repo":"apache/kafka","slug":"the-maximum-value-max-must-be-greater-than-the-m","errorCode":null,"errorMessage":"The maximum value {max} must be greater than the minimum value {min}","messagePattern":"The maximum value (.+?) must be greater than the minimum value (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java","lineNumber":90,"sourceCode":"    private final BinScheme binScheme;\n\n    /**\n     * Create a Frequencies that captures the values in the specified range into the given number of buckets,\n     * where the buckets are centered around the minimum, maximum, and intermediate values.\n     *\n     * @param buckets     the number of buckets; must be at least 1\n     * @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    }","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java#L72-L108","documentation":"Thrown by the Frequencies constructor when max < min, i.e. the supplied range is empty or inverted. Frequencies buckets values between min and max using a ConstantBinScheme; an inverted range makes bucketing meaningless (bucket width and centers become negative or undefined). The check enforces max >= min; note equality is permitted but the bucket math (line 106) divides by (buckets - 1), so equal endpoints with a single bucket are the only valid degenerate case.","triggerScenarios":"Constructing new Frequencies(buckets, min, max, frequencies) with min > max (arguments supplied in the wrong order, or values read from config that are inverted). Also triggered by swapping the positional min/max arguments when calling the constructor.","commonSituations":"Config-driven thresholds where an operator set the lower bound higher than the upper bound; copy-paste swapping min and max positions; using latency in seconds for one bound and milliseconds for the other producing an apparent inversion.","solutions":["Ensure max >= min; for boolean use Frequencies.forBooleanValues(false, true) which correctly uses 0.0..1.0.","Validate config at load time and reject/swap inverted bounds with a clear error before constructing Frequencies.","Double-check units (ms vs s, bytes vs bits) for both bounds — unit mismatches are the usual cause of apparent inversion."],"exampleFix":"// before\nnew Frequencies(5, 100.0, 0.0, freqs); // max < min\n// after\nnew Frequencies(5, 0.0, 100.0, freqs); // min < max","handlingStrategy":"validation","validationCode":"// Pre-validate the range before constructing Frequencies:\nif (!Double.isFinite(min) || !Double.isFinite(max)) {\n    throw new IllegalArgumentException(\"min and max must be finite\");\n}\nif (!(max > min)) { // also rejects max == min (degenerate range) and NaN\n    throw new IllegalArgumentException(\"max (\" + max + \") must be > min (\" + min + \")\");\n}\nreturn new Frequencies(buckets, min, max, frequencies);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a strictly increasing (min, max) pair; equal endpoints are not allowed.","Reject NaN/Infinity upstream — they silently break the max > min comparison.","If you read min/max from configuration, validate at config-load time, not at metric creation."],"tags":["metrics","validation","configuration"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}