apache/pulsar · error · IllegalArgumentException

Key hash ranges with overlap between and

Error message

Key hash ranges with overlap between  and 

What it means

ReaderBuilder.keyHashRange() requires the supplied ranges to be mutually disjoint; overlapping ranges make key assignment for a non-overlapping reader ambiguous. When Range.intersect(range2) returns non-null for two distinct ranges, this IllegalArgumentException is thrown.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/ReaderBuilderImpl.java:246

    @Override
    public ReaderBuilder<T> readCompacted(boolean readCompacted) {
        conf.setReadCompacted(readCompacted);
        return this;
    }

    @Override
    public ReaderBuilder<T> keyHashRange(Range... ranges) {
        checkArgument(ranges != null && ranges.length > 0,
                "Cannot specify a null ofr an empty key hash ranges for a reader");
        for (int i = 0; i < ranges.length; i++) {
            Range range1 = ranges[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.length; j++) {
                Range range2 = ranges[j];
                if (i != j && range1.intersect(range2) != null) {
                    throw new IllegalArgumentException("Key hash ranges with overlap between " + range1
                            + " and " + range2);
                }
            }
        }
        conf.setKeyHashRanges(Arrays.asList(ranges));
        return this;
    }

    @Override
    public ReaderBuilder<T> poolMessages(boolean poolMessages) {
        conf.setPoolMessages(poolMessages);
        return this;
    }

    @Override
    public ReaderBuilder<T> autoUpdatePartitions(boolean autoUpdate) {
        this.conf.setAutoUpdatePartitions(autoUpdate);
        return this;

View on GitHub (pinned to 820761864e)

Solutions

  1. Make ranges strictly non-overlapping, e.g. [0, 32766] and [32767, 65535] with inclusive endpoints
  2. De-duplicate the ranges array before passing it
  3. Validate pairwise intersections in your own code before calling keyHashRange

Example fix

// before
readerBuilder.keyHashRange(Range.of(0, 32767), Range.of(32767, 65535)); // 32767 overlaps
// after
readerBuilder.keyHashRange(Range.of(0, 32766), Range.of(32767, 65535));
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i < ranges.length; i++) {
    for (int j = i + 1; j < ranges.length; j++) {
        if (ranges[i].intersect(ranges[j]) != null) {
            throw new IllegalArgumentException("Overlapping ranges: " + ranges[i] + " and " + ranges[j]);
        }
    }
}

Type guard

boolean areDisjoint(Range... ranges) {
    for (int i = 0; i < ranges.length; i++)
        for (int j = i + 1; j < ranges.length; j++)
            if (ranges[i].intersect(ranges[j]) != null) return false;
    return true;
}

Try / catch

try {
    readerBuilder.keyHashRange(ranges);
} catch (IllegalArgumentException e) {
    log.error("Overlapping key hash ranges: {}", e.getMessage());
    throw new ConfigurationException("Key hash ranges must be disjoint", e);
}

Prevention

When it happens

Trigger: Calling keyHashRange with two or more ranges that share any portion of the [0,65535] space, e.g. Range.of(0, 32767) and Range.of(32767, 65535) (both contain 32767), or duplicated ranges like (0,10) specified twice.

Common situations: Splitting the hash space at shared boundaries while forgetting range endpoints are inclusive, generating ranges programmatically with a step that overlaps at boundaries, or passing the same range twice in the varargs list.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/20e1104ad7ff3675. Report an issue: GitHub.