{"record":{"id":"417f130623b79b90","repo":"redis/jedis","slug":"limit-offset-and-count-must-be-non-negative","errorCode":null,"errorMessage":"LIMIT offset and count must be non-negative","messagePattern":"LIMIT offset and count must be non-negative","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/search/aggr/CollectReducer.java","lineNumber":130,"sourceCode":"    this.sortFields.add(SortedField.asc(field));\n    return this;\n  }\n\n  /** Convenience for {@code sortBy(SortedField.desc(field))}. */\n  public CollectReducer sortByDesc(String field) {\n    this.sortFields.add(SortedField.desc(field));\n    return this;\n  }\n\n  /** Bound the output per group to the first {@code count} entries (offset 0). */\n  public CollectReducer limit(int count) {\n    return limit(0, count);\n  }\n\n  /** Bound the output per group to {@code count} entries starting at {@code offset}. */\n  public CollectReducer limit(int offset, int count) {\n    if (offset < 0 || count < 0) {\n      throw new IllegalArgumentException(\"LIMIT offset and count must be non-negative\");\n    }\n    this.limitOffset = offset;\n    this.limitCount = count;\n    return this;\n  }\n\n  @Override\n  protected List<Object> getOwnArgs() {\n    if (!allFields && fields.isEmpty()) {\n      throw new IllegalStateException(\n          \"REDUCE COLLECT requires either fields(...) or fieldsAll() to be configured\");\n    }\n\n    List<Object> args = new ArrayList<>();\n    args.add(SearchKeyword.FIELDS);\n    if (allFields) {\n      args.add(Protocol.BYTES_ASTERISK);\n    } else {","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/search/aggr/CollectReducer.java#L112-L148","documentation":"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.","triggerScenarios":"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.","commonSituations":"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().","solutions":["Validate/clamp offset and count to >= 0 before calling limit","For 'no limit' behavior, omit the limit() call instead of passing -1","Fix pagination arithmetic: use offset = page * size with page starting at 0, or Math.max(0, computed)"],"exampleFix":"// before\nreducer.limit(page - 1, pageSize); // IllegalArgumentException when page==0\n// after\nreducer.limit(Math.max(0, (page - 1)) * pageSize, Math.max(0, pageSize));","handlingStrategy":"validation","validationCode":"if (offset < 0 || count < 0) {\n  throw new IllegalArgumentException(\"limit offset/count must be >= 0\");\n}\nreducer.limit(offset, count);","typeGuard":"null","tryCatchPattern":"try {\n  reducer.limit(offset, count);\n} catch (IllegalArgumentException e) {\n  // clamp or correct pagination math before retrying\n}","preventionTips":["Clamp user-supplied paging values with Math.max(0, x) before calling limit","Omit limit() entirely for unlimited output instead of passing -1","Audit pagination arithmetic for off-by-one negatives (page starting at 1 vs 0)"],"tags":["jedis","search","aggregation","limit","argument-validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}