redis/jedis · error · IllegalArgumentException

LIMIT offset and count must be non-negative

Error message

LIMIT offset and count must be non-negative

What it means

CollectReducer.limit(offset, count) implements the aggregation LIMIT clause, which only accepts non-negative offset and count values. Passing either negative throws this IllegalArgumentException before any query is sent, preventing an invalid query from reaching the server.

Solutions

  1. Validate/clamp offset and count to >= 0 before calling limit
  2. For 'no limit' behavior, omit the limit() call instead of passing -1
  3. Fix pagination arithmetic: use offset = page * size with page starting at 0, or Math.max(0, computed)

Example fix

// before
reducer.limit(page - 1, pageSize); // IllegalArgumentException when page==0
// after
reducer.limit(Math.max(0, (page - 1)) * pageSize, Math.max(0, pageSize));
Defensive patterns

Strategy: validation

Validate before calling

if (offset < 0 || count < 0) {
  throw new IllegalArgumentException("limit offset/count must be >= 0");
}
reducer.limit(offset, count);

Type guard

null

Try / catch

try {
  reducer.limit(offset, count);
} catch (IllegalArgumentException e) {
  // clamp or correct pagination math before retrying
}

Prevention

When it happens

Trigger: Calling limit(-1, 10) or limit(0, -5) — commonly from computed/unvalidated user input or off-by-one arithmetic such as pageSize-1 with pageSize=0.

Common situations: Pagination math going negative (page=0 leading to offset=(page-1)*size); user-supplied limits clamped too late; defaults of -1 used as 'unlimited' sent straight to limit().

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/417f130623b79b90. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/search/aggr/CollectReducer.java:130

    this.sortFields.add(SortedField.asc(field));
    return this;
  }

  /** Convenience for {@code sortBy(SortedField.desc(field))}. */
  public CollectReducer sortByDesc(String field) {
    this.sortFields.add(SortedField.desc(field));
    return this;
  }

  /** Bound the output per group to the first {@code count} entries (offset 0). */
  public CollectReducer limit(int count) {
    return limit(0, count);
  }

  /** Bound the output per group to {@code count} entries starting at {@code offset}. */
  public CollectReducer limit(int offset, int count) {
    if (offset < 0 || count < 0) {
      throw new IllegalArgumentException("LIMIT offset and count must be non-negative");
    }
    this.limitOffset = offset;
    this.limitCount = count;
    return this;
  }

  @Override
  protected List<Object> getOwnArgs() {
    if (!allFields && fields.isEmpty()) {
      throw new IllegalStateException(
          "REDUCE COLLECT requires either fields(...) or fieldsAll() to be configured");
    }

    List<Object> args = new ArrayList<>();
    args.add(SearchKeyword.FIELDS);
    if (allFields) {
      args.add(Protocol.BYTES_ASTERISK);
    } else {

View on GitHub (pinned to 6dac31d4c2)