apache/pulsar · error · IllegalArgumentException
Ranges for KeyShared policy must not be empty.
Error message
Ranges for KeyShared policy must not be empty.
What it means
KeySharedPolicy.KeySharedPolicySticky.validate() rejects a sticky ranges policy whose list of hash ranges is empty, throwing IllegalArgumentException. A sticky KeyShared consumer must partition the 0-65535 hash space into at least one non-empty range; an empty list would leave the consumer unable to receive any messages.
Source
Thrown at pulsar-client-api/src/main/java/org/apache/pulsar/client/api/KeySharedPolicy.java:109
KeySharedPolicySticky() {
this.keySharedMode = KeySharedMode.STICKY;
this.ranges = new ArrayList<>();
}
public KeySharedPolicySticky ranges(List<Range> ranges) {
this.ranges.addAll(ranges);
return this;
}
public KeySharedPolicySticky ranges(Range... ranges) {
this.ranges.addAll(Arrays.asList(ranges));
return this;
}
@Override
public void validate() {
if (ranges.isEmpty()) {
throw new IllegalArgumentException("Ranges for KeyShared policy must not be empty.");
}
for (int i = 0; i < ranges.size(); i++) {
Range range1 = ranges.get(i);
if (range1.getStart() < 0 || range1.getEnd() >= DEFAULT_HASH_RANGE_SIZE) {
throw new IllegalArgumentException("Ranges must be [0, 65535] but provided range is " + range1);
}
for (int j = 0; j < ranges.size(); j++) {
Range range2 = ranges.get(j);
if (i != j && range1.intersect(range2) != null) {
throw new IllegalArgumentException("Ranges for KeyShared policy with overlap between " + range1
+ " and " + range2);
}
}
}
}
public List<Range> getRanges() {
return ranges;View on GitHub (pinned to 820761864e)
Solutions
- Provide at least one Range, e.g. Range.of(0, 65535) to cover the full hash space.
- Fix range-splitting code so it always yields non-empty ranges for all consumers.
- Catch IllegalArgumentException and fall back to KeySharedPolicy.autoSplitHashRange() when no ranges are configured.
- Ensure each range is within [0, 65535] to avoid the related out-of-range error.
Example fix
// before
KeySharedPolicy policy = KeySharedPolicy.stickyRanges()
.ranges(Collections.emptyList());
// after
KeySharedPolicy policy = KeySharedPolicy.stickyRanges()
.ranges(Collections.singletonList(Range.of(0, 65535))); Defensive patterns
Strategy: validation
Validate before calling
List<Range> ranges = /* computed ranges */;
if (ranges == null || ranges.isEmpty()) {
ranges = Collections.singletonList(Range.of(0, 65535));
}
ranges.forEach(r -> {
if (r.getStart() < 0 || r.getEnd() >= 65536) {
throw new IllegalArgumentException("Range out of [0,65535]: " + r);
}
});
KeySharedPolicy policy = KeySharedPolicy.stickyRanges().ranges(ranges); Try / catch
try {
consumerBuilder.keySharedPolicy(stickyPolicy);
} catch (IllegalArgumentException e) {
log.warn("Invalid sticky ranges, falling back to auto split: {}", e.getMessage());
consumerBuilder.keySharedPolicy(KeySharedPolicy.autoSplitHashRange());
} Prevention
- Cover the full 0-65535 hash space with your ranges and never leave the list empty.
- Guard range-splitting code against producing zero ranges (e.g. when splitting across 0 consumers).
- Fall back to KeySharedPolicy.autoSplitHashRange() when sticky ranges cannot be computed.
When it happens
Trigger: ConsumerBuilder.keySharedPolicy(KeySharedPolicy.stickyRanges().ranges(new ArrayList<>())) or an empty Range list passed to ranges(...), then subscribe()/validate runs. Also fired when the list itself is empty even if individual ranges would be valid.
Common situations: Computing ranges programmatically (e.g. splitting the hash space across N consumers) when N is 0 or the split logic returns nothing; copying example code but clearing the ranges list; building the policy from empty configuration.
Related errors
- entryFilterNames can't be empty. To remove entry filters use
- The offloadPolicies must be specified for namespace offload.
- The bucket must be specified for namespace offload.
- cluster data is required
- Can not enable for all producers but denies for replicators,
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/f63675ad4894af39.
Report an issue: GitHub.