apache/kafka · error · IllegalArgumentException

The maximum value {max} must be greater than the minimum val

Error message

The maximum value {max} must be greater than the minimum value {min}

What it means

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.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java:90

    private final BinScheme binScheme;

    /**
     * Create a Frequencies that captures the values in the specified range into the given number of buckets,
     * where the buckets are centered around the minimum, maximum, and intermediate values.
     *
     * @param buckets     the number of buckets; must be at least 1
     * @param min         the minimum value to be captured
     * @param max         the maximum value to be captured
     * @param frequencies the list of {@link Frequency} metrics, which at most should be one per bucket centered
     *                    on the bucket's value, though not every bucket need to correspond to a metric if the
     *                    value is not needed
     * @throws IllegalArgumentException if any of the {@link Frequency} objects do not have a
     *                                  {@link Frequency#centerValue() center value} within the specified range
     */
    public Frequencies(int buckets, double min, double max, Frequency... frequencies) {
        super(0.0); // initial value is unused by this implementation
        if (max < min) {
            throw new IllegalArgumentException("The maximum value " + max
                                                       + " must be greater than the minimum value " + min);
        }
        if (buckets < 1) {
            throw new IllegalArgumentException("Must be at least 1 bucket");
        }
        if (buckets < frequencies.length) {
            throw new IllegalArgumentException("More frequencies than buckets");
        }
        this.frequencies = frequencies;
        for (Frequency freq : frequencies) {
            if (min > freq.centerValue() || max < freq.centerValue()) {
                throw new IllegalArgumentException("The frequency centered at '" + freq.centerValue()
                                                           + "' is not within the range [" + min + "," + max + "]");
            }
        }
        double halfBucketWidth = (max - min) / (buckets - 1) / 2.0;
        this.binScheme = new ConstantBinScheme(buckets, min - halfBucketWidth, max + halfBucketWidth);
    }

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Ensure max >= min; for boolean use Frequencies.forBooleanValues(false, true) which correctly uses 0.0..1.0.
  2. Validate config at load time and reject/swap inverted bounds with a clear error before constructing Frequencies.
  3. Double-check units (ms vs s, bytes vs bits) for both bounds — unit mismatches are the usual cause of apparent inversion.

Example fix

// before
new Frequencies(5, 100.0, 0.0, freqs); // max < min
// after
new Frequencies(5, 0.0, 100.0, freqs); // min < max
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate the range before constructing Frequencies:
if (!Double.isFinite(min) || !Double.isFinite(max)) {
    throw new IllegalArgumentException("min and max must be finite");
}
if (!(max > min)) { // also rejects max == min (degenerate range) and NaN
    throw new IllegalArgumentException("max (" + max + ") must be > min (" + min + ")");
}
return new Frequencies(buckets, min, max, frequencies);

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/7d4e5717ea45bc4f.json. Report an issue: GitHub.