{"record":{"id":"729078824348fbd5","repo":"apache/pulsar","slug":"ranges-must-be-0-65535-but-provided-range-is-729078","errorCode":null,"errorMessage":"Ranges must be [0, 65535] but provided range is ","messagePattern":"Ranges must be \\[0, 65535\\] but provided range is ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api/src/main/java/org/apache/pulsar/client/api/KeySharedPolicy.java","lineNumber":114,"sourceCode":"        public KeySharedPolicySticky ranges(List<Range> ranges) {\n            this.ranges.addAll(ranges);\n            return this;\n        }\n\n        public KeySharedPolicySticky ranges(Range... ranges) {\n            this.ranges.addAll(Arrays.asList(ranges));\n            return this;\n        }\n\n        @Override\n        public void validate() {\n            if (ranges.isEmpty()) {\n                throw new IllegalArgumentException(\"Ranges for KeyShared policy must not be empty.\");\n            }\n            for (int i = 0; i < ranges.size(); i++) {\n                Range range1 = ranges.get(i);\n                if (range1.getStart() < 0 || range1.getEnd() >= DEFAULT_HASH_RANGE_SIZE) {\n                    throw new IllegalArgumentException(\"Ranges must be [0, 65535] but provided range is \" + range1);\n                }\n                for (int j = 0; j < ranges.size(); j++) {\n                    Range range2 = ranges.get(j);\n                    if (i != j && range1.intersect(range2) != null) {\n                        throw new IllegalArgumentException(\"Ranges for KeyShared policy with overlap between \" + range1\n                                + \" and \" + range2);\n                    }\n                }\n            }\n        }\n\n        public List<Range> getRanges() {\n            return ranges;\n        }\n    }\n\n    /**\n     * Auto split hash range key shared policy.","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/KeySharedPolicy.java#L96-L132","documentation":"KeySharedPolicy.KeySharedPolicySticky.validate() rejects a sticky hash range whose start is negative or whose end is >= DEFAULT_HASH_RANGE_SIZE (65535). Pulsar's KeyShared sticky dispatcher maps message keys onto a fixed 0..65535 hash space, so any range outside those bounds can never match a key and would silently steal/lose assignments. The library fails fast with IllegalArgumentException at attach time rather than mis-routing at runtime.","triggerScenarios":"Calling KeySharedPolicy.stickyRanges(...) (then attaching a consumer) with a Range built as Range.of(-1, 100) or Range.of(0, 65535) — any range whose start < 0 or end >= 65535 passes into validate().","commonSituations":"Off-by-one: developers assume the range is inclusive of 65535 like a 16-bit unsigned value, writing Range.of(0, 65535); treating the range as 1-based (starting at 1 is fine but ending at 65535 is not); hand-computed partitions after resizing that drift below zero.","solutions":["Clamp every range so start >= 0 and end <= 65534 (the valid hash space is [0, 65535) exclusive at the top).","Replace Range.of(0, 65535) with Range.of(0, 65534) for a full-space single range.","Validate ranges client-side with Range.of and a bounds check before building the policy, so the consumer fails at construction, not at subscribe."],"exampleFix":"// before\nKeySharedPolicy policy = KeySharedPolicy.stickyRanges(\n    Collections.singletonList(Range.of(0, 65535)));\n// after\nKeySharedPolicy policy = KeySharedPolicy.stickyRanges(\n    Collections.singletonList(Range.of(0, 65534))); // max end is 65534","handlingStrategy":"validation","validationCode":"static void checkRange(Range r) {\n    if (r.getStart() < 0 || r.getEnd() >= 65535)\n        throw new IllegalArgumentException(\"Range out of [0, 65535): \" + r);\n}\nranges.forEach(MyClass::checkRange); // before KeySharedPolicy.stickyRanges(...)","typeGuard":"static boolean isValidHashRange(Range r) {\n    return r != null && r.getStart() >= 0 && r.getEnd() < 65535;\n}","tryCatchPattern":"try {\n    consumer = client.newConsumer().keySharedPolicy(KeySharedPolicy.stickyRanges(ranges)).subscribe();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Ranges must be [0, 65535]\")) {\n        // fix or clamp the offending range reported in e.getMessage()\n    } else throw e;\n}","preventionTips":["Remember the hash space is [0, 65535) — the maximum valid end value is 65534.","Generate sticky ranges by partitioning the space programmatically instead of hardcoding boundaries.","Add a unit test asserting every configured range satisfies start >= 0 && end < 65535."],"tags":["keyshared","hash-range","illegal-argument","client-config"],"backgroundTag":"hash-range-out-of-bounds","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}