{"id":"28bb8d1bbe63b359","repo":"apache/kafka","slug":"s-absent-in-s","errorCode":null,"errorMessage":"%s absent in [%s]","messagePattern":"(.+?) absent in \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/feature/BaseVersionRange.java","lineNumber":136,"sourceCode":"            return false;\n        }\n\n        final BaseVersionRange that = (BaseVersionRange) other;\n        return Objects.equals(this.minKeyLabel, that.minKeyLabel) &&\n            this.minValue == that.minValue &&\n            Objects.equals(this.maxKeyLabel, that.maxKeyLabel) &&\n            this.maxValue == that.maxValue;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(minKeyLabel, minValue, maxKeyLabel, maxValue);\n    }\n\n    public static short valueOrThrow(String key, Map<String, Short> versionRangeMap) {\n        final Short value = versionRangeMap.get(key);\n        if (value == null) {\n            throw new IllegalArgumentException(String.format(\"%s absent in [%s]\", key, mapToString(versionRangeMap)));\n        }\n        return value;\n    }\n}\n","sourceCodeStart":118,"sourceCodeEnd":141,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/feature/BaseVersionRange.java#L118-L141","documentation":"Thrown as IllegalArgumentException by BaseVersionRange.valueOrThrow(key, map) when the given key is absent from the version-range map. valueOrThrow is the helper used by fromMap() factories on subclasses to extract the min/max version: if the deserialized map is missing the expected label (e.g. 'min_version' or 'max_version'), it cannot be reconstructed and this fires. The message prints both the missing key and a dump of the map's actual contents, making schema mismatches obvious.","triggerScenarios":"Calling valueOrThrow(\"min_version\", map) on a map that lacks that key; subclass fromMap() deserializing a features map whose keys are misspelled, uppercased, or from an incompatible schema; tests passing a hand-built map with one of the entries omitted.","commonSituations":"Inter-version incompatibility: a newer broker writes feature map keys that an older client does not expect (or vice versa); a forged/hand-edited metadata payload; tests constructing maps with literal keys that don't match the subclass constants.","solutions":["Compare the key in the error message to the map contents also printed in the message: fix the typo or migrate the schema.","When deserializing untrusted/foreign maps, catch IllegalArgumentException and surface a deserialization error rather than crashing.","If this occurs during broker-controller handshake, verify both sides run compatible Kafka versions and that no third-party tool mutated the feature map keys.","In tests, build the input map through the same constants the subclass uses (e.g. fromMap(range.toMap())) instead of hand-typing keys."],"exampleFix":"// before\nMap<String,Short> m = new HashMap<>();\nm.put(\"minVersion\", (short) 1);   // wrong key\nshort min = BaseVersionRange.valueOrThrow(\"min_version\", m);\n\n// after\nMap<String,Short> m = new HashMap<>();\nm.put(\"min_version\", (short) 1);\nm.put(\"max_version\", (short) 3);\nshort min = BaseVersionRange.valueOrThrow(\"min_version\", m);","handlingStrategy":"validation","validationCode":"Short value = versionRangeMap.get(key);\nif (value == null) {\n    // key absent: skip, default, or raise a domain-specific error\n} else {\n    // use value; avoid calling BaseVersionRange.valueOrThrow unless you want exactly its exception\n}","typeGuard":"static boolean hasVersionKey(java.util.Map<String,Short> map, String key) {\n    return key != null && map != null && map.containsKey(key);\n}","tryCatchPattern":"try {\n    short v = BaseVersionRange.valueOrThrow(key, versionRangeMap);\n} catch (IllegalArgumentException e) {\n    // message: \"<key> absent in [...]\"\n    // the feature/version is unknown; negotiate a safe lower version or skip the feature\n}","preventionTips":["Prefer Map.containsKey(key) (or a null check on get) over valueOrThrow when you can tolerate absence","Validate the version-range map schema before reading keys from it","Treat absence as a negotiation signal: fall back to a known-safe default version rather than crashing","Log the entire map contents in the catch so operators can see what keys were actually present"],"tags":["feature-negotiation","version-range","deserialization","illegal-argument"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}