apache/kafka · error · IllegalArgumentException

Expected minKeyLabel to be non-empty.

Error message

Expected minKeyLabel to be non-empty.

What it means

Thrown as IllegalArgumentException by the BaseVersionRange constructor when minKeyLabel is the empty string. The min/max key labels are the map keys used when serializing the range to/from a Map (e.g. 'min_version' / 'max_version'); an empty label would produce an ambiguous, unparseable map, so the constructor rejects it eagerly. Subclasses supply these labels, so the error is almost always a subclass-implementation bug, not end-user input.

Source

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

     *
     * @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;
    }

    public short max() {
        return maxValue;
    }

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Check the subclass: confirm the minKeyLabel passed to super(...) is a non-empty literal/constant (e.g. "min_version").
  2. If the label is derived from configuration or input, validate non-empty before invoking the constructor and fail with a domain-specific error instead.
  3. Add a unit test that constructs the subclass with its default labels to lock in the invariant.

Example fix

// before
class MyVersionRange extends BaseVersionRange {
    MyVersionRange(short min, short max) {
        super("", min, "max_version", max);
    }
}

// after
class MyVersionRange extends BaseVersionRange {
    MyVersionRange(short min, short max) {
        super("min_version", min, "max_version", max);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

String minKeyLabel = ...;
if (minKeyLabel == null || minKeyLabel.isEmpty()) {
    throw new IllegalArgumentException("minKeyLabel must be non-empty");
}
// safe to proceed

Type guard

static boolean isValidKeyLabel(String label) {
    return label != null && !label.isEmpty();
}

Try / catch

try {
    // construct the version range with minKeyLabel
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("minKeyLabel")) {
        // supply a default label or fail configuration loading
    } else { throw e; }
}

Prevention

When it happens

Trigger: A subclass of BaseVersionRange passes "" as minKeyLabel to super(...); invoking fromMap() on a map whose structure was tampered with cannot itself trigger this (fromMap uses valueOrThrow, not the empty-label check), so the trigger is always direct construction with a bad label constant.

Common situations: Introducing a new BaseVersionRange subclass and forgetting to initialize the label constant; a refactor that replaces a constant with a field that is null-or-empty at super() call time; copy-paste errors where min and max labels are swapped or one is dropped.

Related errors


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