apache/pulsar · error · IllegalArgumentException

Range end must >= range start.

Error message

Range end must >= range start.

What it means

The Range constructor validates that end >= start and throws IllegalArgumentException otherwise. A Range with an inverted interval is meaningless in Pulsar's hash-space model (used for KeyShared sticky ranges), so the constructor refuses to create such an object rather than propagating a broken invariant to downstream intersection/containment logic.

Source

Thrown at pulsar-client-api/src/main/java/org/apache/pulsar/client/api/Range.java:40

import java.util.Objects;
import org.apache.pulsar.common.classification.InterfaceAudience;
import org.apache.pulsar.common.classification.InterfaceStability;

/**
 * Int range.
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class Range implements Comparable<Range>, Serializable {
    private static final long serialVersionUID = 1L;

    private final int start;
    private final int end;


    public Range(int start, int end) {
        if (end < start) {
            throw new IllegalArgumentException("Range end must >= range start.");
        }
        this.start = start;
        this.end = end;
    }

    public static Range of(int start, int end) {
        return new Range(start, end);
    }

    public int getStart() {
        return start;
    }

    public int getEnd() {
        return end;
    }

    public Range intersect(Range range) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Swap the arguments so the smaller value is the start: Range.of(Math.min(a, b), Math.max(a, b)).
  2. Normalize inputs before constructing: reject or clamp inverted intervals in your own config-loading code.
  3. If a range legitimately became empty, model it explicitly (skip it) rather than constructing an inverted Range.

Example fix

// before
Range range = Range.of(end, start);
// after
Range range = Range.of(Math.min(start, end), Math.max(start, end));
Defensive patterns

Strategy: validation

Validate before calling

static Range safeRange(int a, int b) {
    if (b < a) throw new IllegalArgumentException("end < start: " + a + ", " + b);
    return Range.of(a, b);
}

Type guard

static boolean isValidInterval(int start, int end) {
    return end >= start;
}

Try / catch

try {
    Range r = Range.of(start, end);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Range end must >= range start")) {
        Range r = Range.of(Math.min(start, end), Math.max(start, end)); // normalize
    } else throw e;
}

Prevention

When it happens

Trigger: Calling new Range(100, 50) or Range.of(100, 50) directly — any construction where the end is strictly less than the start.

Common situations: Swapped arguments when computing range boundaries from variables (Range.of(end, start)); computing start/end from user input or config where the ordering was never normalized; splitting logic that emits (high, low) by mistake.

Related errors


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