quarkusio/quarkus · error · IllegalArgumentException

Last index must be >= 0:

Error message

Last index must be >= 0: 

What it means

Thrown by the Range constructor when lastIndex is negative. Range models an inclusive 0-based index window for Panache queries (and, per the class note, cannot represent empty ranges); a negative end index would describe a backwards or empty window, so the constructor guard rejects it immediately — mirroring the preceding check that startIndex must be >= 0.

Source

Thrown at extensions/panache/panache-common/runtime/src/main/java/io/quarkus/panache/common/Range.java:33

 *
 * Note that due to the end index being inclusive, it's impossible to write empty ranges.
 */
public class Range {
    // FIXME: bump to long? Jakarta Data uses longs for its Limit type
    private final int startIndex;
    private final int lastIndex;

    /**
     * Creates a new range
     *
     * @param startIndex the start index to include, 0-based
     * @param lastIndex the end index to include, 0-based
     */
    public Range(int startIndex, int lastIndex) {
        if (startIndex < 0)
            throw new IllegalArgumentException("Start index must be >= 0: " + startIndex);
        if (lastIndex < 0)
            throw new IllegalArgumentException("Last index must be >= 0: " + lastIndex);
        if (lastIndex < startIndex)
            throw new IllegalArgumentException(
                    "Last index must be >= start index: " + lastIndex + " is not larger or equal to " + startIndex);
        this.startIndex = startIndex;
        this.lastIndex = lastIndex;
    }

    /**
     * Creates a new range
     *
     * @param startIndex the start index to include, 0-based
     * @param lastIndex the end index to include, 0-based
     */
    public static Range of(int startIndex, int lastIndex) {
        return new Range(startIndex, lastIndex);
    }

    /**

View on GitHub (pinned to e1c734241f)

Solutions

  1. Validate inputs: reject or clamp lastIndex to >= 0 before constructing.
  2. Handle the empty-window case explicitly (skip the query or use Range.of(0, 0)) instead of computing end=-1.
  3. Return HTTP 400 for client-supplied negative end indexes.

Example fix

// before
Range r = Range.of(0, count - 1); // count=0 -> -1
// after
if (count > 0) { Range r = Range.of(0, count - 1); ... }
Defensive patterns

Strategy: validation

Validate before calling

int end = /* computed */;
if (end < 0) throw new BadRequestException("lastIndex must be >= 0");
Range r = Range.of(start, end);

Type guard

Range safeRange(int start, int last) {
    int s = Math.max(0, start);
    return Range.of(s, Math.max(s, last));
}

Try / catch

try {
    Range r = Range.of(start, last);
} catch (IllegalArgumentException e) {
    throw new BadRequestException("Invalid range: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling new Range(0, -1) or Range.of with a negative end — e.g. end computed as start+count-1 with count=0, or an unvalidated negative lastIndex input.

Common situations: Empty result windows (count 0 leading to end=-1); client-provided negative end parameters; slice math on empty collections.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/29bbe2ee1b6f3788. Report an issue: GitHub.