{"id":"89d79ec22120fe4e","repo":"apache/kafka","slug":"expected-maxkeylabel-to-be-non-empty","errorCode":null,"errorMessage":"Expected maxKeyLabel to be non-empty.","messagePattern":"Expected maxKeyLabel to be non-empty\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/feature/BaseVersionRange.java","lineNumber":73,"sourceCode":"     * @param maxKeyLabel   Label for the max version key, that's used only to convert to/from a map.\n     * @param maxValue      The maximum version value.\n     *\n     * @throws IllegalArgumentException   If any of the following conditions are true:\n     *                                     - (minValue < 0) OR (maxValue < 0) OR (maxValue < minValue).\n     *                                     - minKeyLabel is empty, OR, minKeyLabel is empty.\n     */\n    protected BaseVersionRange(String minKeyLabel, short minValue, String maxKeyLabel, short maxValue) {\n        if (minValue < 0 || maxValue < 0 || maxValue < minValue) {\n            throw new IllegalArgumentException(\n                String.format(\n                    \"Expected minValue >= 0, maxValue >= 0 and maxValue >= minValue, but received\" +\n                    \" minValue: %d, maxValue: %d\", minValue, maxValue));\n        }\n        if (minKeyLabel.isEmpty()) {\n            throw new IllegalArgumentException(\"Expected minKeyLabel to be non-empty.\");\n        }\n        if (maxKeyLabel.isEmpty()) {\n            throw new IllegalArgumentException(\"Expected maxKeyLabel to be non-empty.\");\n        }\n        this.minKeyLabel = minKeyLabel;\n        this.minValue = minValue;\n        this.maxKeyLabel = maxKeyLabel;\n        this.maxValue = maxValue;\n    }\n\n    public short min() {\n        return minValue;\n    }\n\n    public short max() {\n        return maxValue;\n    }\n\n    @Override\n    public String toString() {\n        return String.format(","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/feature/BaseVersionRange.java#L55-L91","documentation":"Thrown as IllegalArgumentException by the BaseVersionRange constructor when maxKeyLabel is the empty string. Symmetric to the minKeyLabel check: the max label is the map key under which the max version is serialized, so an empty label is rejected up-front to keep round-trip (range -> map -> range) well-defined. Triggered only by direct construction with a bad label, almost always a subclass bug.","triggerScenarios":"A subclass passes \"\" as maxKeyLabel to the BaseVersionRange constructor; a refactor leaves the max label constant unset while min is fine.","commonSituations":"New feature-range subclass with a typo/dropped constant; refactor replacing constants with computed fields that evaluate to empty at super() time.","solutions":["Verify the maxKeyLabel argument passed to super(...) is a non-empty constant (e.g. \"max_version\").","Guard any externally-supplied label at the boundary before construction.","Add a construction test for the subclass to prevent regression."],"exampleFix":"// before\nsuper(\"min_version\", min, \"\", max);\n\n// after\nsuper(\"min_version\", min, \"max_version\", max);","handlingStrategy":"validation","validationCode":"String maxKeyLabel = ...;\nif (maxKeyLabel == null || maxKeyLabel.isEmpty()) {\n    throw new IllegalArgumentException(\"maxKeyLabel must be non-empty\");\n}\n// safe to proceed","typeGuard":"static boolean isValidKeyLabel(String label) {\n    return label != null && !label.isEmpty();\n}","tryCatchPattern":"try {\n    // construct the version range with maxKeyLabel\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"maxKeyLabel\")) {\n        // supply a default label or fail configuration loading\n    } else { throw e; }\n}","preventionTips":["Do not derive maxKeyLabel from external/user input without a non-empty check","Use constants for well-known labels (e.g. \"max_version\") instead of computed strings","Pair the min/max label validation so a copy-paste of one to the other cannot silently produce empty","Validate label strings at the configuration parsing boundary"],"tags":["feature-negotiation","version-range","validation","illegal-argument"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}