apache/kafka · error · IllegalArgumentException

Expected minValue >= 0, maxValue >= 0 and maxValue >= minVal

Error message

Expected minValue >= 0, maxValue >= 0 and maxValue >= minValue, but received minValue: %d, maxValue: %d

What it means

Thrown as IllegalArgumentException by the BaseVersionRange constructor when the supplied minValue/maxValue pair violates the invariant minValue >= 0 AND maxValue >= 0 AND maxValue >= minValue. BaseVersionRange (and its subclasses like SupportedVersionRange / FinalizedVersionRange) model negotiated feature versions as non-negative shorts, so a negative value or an inverted range is treated as a programming error rather than a runtime condition. The message echoes both received values to make the violation obvious.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/feature/BaseVersionRange.java:64

    // The value of the maximum version.
    private final short maxValue;

    /**
     * Raises an exception unless the following condition is met:
     * minValue >= 0 and maxValue >= 0 and maxValue >= minValue.
     *
     * @param minKeyLabel   Label for the min version key, that's used only to convert to/from a map.
     * @param minValue      The minimum version value.
     * @param maxKeyLabel   Label for the max version key, that's used only to convert to/from a map.
     * @param maxValue      The maximum version value.
     *
     * @throws IllegalArgumentException   If any of the following conditions are true:
     *                                     - (minValue < 0) OR (maxValue < 0) OR (maxValue < minValue).
     *                                     - minKeyLabel is empty, OR, minKeyLabel is empty.
     */
    protected BaseVersionRange(String minKeyLabel, short minValue, String maxKeyLabel, short maxValue) {
        if (minValue < 0 || maxValue < 0 || maxValue < minValue) {
            throw new IllegalArgumentException(
                String.format(
                    "Expected minValue >= 0, maxValue >= 0 and maxValue >= minValue, but received" +
                    " minValue: %d, maxValue: %d", minValue, maxValue));
        }
        if (minKeyLabel.isEmpty()) {
            throw new IllegalArgumentException("Expected minKeyLabel to be non-empty.");
        }
        if (maxKeyLabel.isEmpty()) {
            throw new IllegalArgumentException("Expected maxKeyLabel to be non-empty.");
        }
        this.minKeyLabel = minKeyLabel;
        this.minValue = minValue;
        this.maxKeyLabel = maxKeyLabel;
        this.maxValue = maxValue;
    }

    public short min() {
        return minValue;

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Inspect the printed minValue/maxValue pair: if minValue>maxValue, swap them; if either is negative, treat it as missing/unset rather than passing -1.
  2. Validate at the boundary that converts external input (REST body, metadata record, CLI flag) into a version range, returning a 4xx / deserialization error instead of constructing the object.
  3. In tests, use the factory methods (e.g. SupportedVersionRange.fromMap) which delegate to the same constructor, so feed them well-formed maps only.
  4. If the values originate from KRaft metadata, dump the feature record and check whether a prior buggy writer produced the inverted values; recover from a known-good snapshot.

Example fix

// before
new SupportedVersionRange((short) 5, (short) 3);

// after
new SupportedVersionRange((short) 3, (short) 5);
Defensive patterns

Strategy: validation

Validate before calling

short minValue = ..., maxValue = ...;
if (minValue < 0 || maxValue < 0 || maxValue < minValue) {
    throw new IllegalArgumentException(
        "Invalid version range: minValue=" + minValue + ", maxValue=" + maxValue);
}
// safe to construct the version range now

Try / catch

try {
    // construct a BaseVersionRange subclass (e.g. SupportedVersionRange)
} catch (IllegalArgumentException e) {
    // message starts with "Expected minValue >= 0, maxValue >= 0 and maxValue >= minValue..."
    // reject the configuration / negotiated feature and continue with defaults
}

Prevention

When it happens

Trigger: Constructing a BaseVersionRange subclass with minValue<0, maxValue<0, or maxValue<minValue (e.g. new SupportedVersionRange((short)-1, (short)2) or new FinalizedVersionRange((short)5, (short)3)). Also reachable from fromMap() / feature-deserialization paths if a corrupted or hand-crafted metadata map feeds in inverted or negative values.

Common situations: Unit tests of feature negotiation passing sentinel values; a corrupted KRaft metadata record or a forged Features protobuf/map containing negative or inverted version fields; downstream tooling that synthesizes FinalizedVersionRange from user input without validating first.

Related errors


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