{"record":{"id":"e659587f8037c2af","repo":"redis/jedis","slug":"reduce-collect-requires-either-fields-or-fiel","errorCode":null,"errorMessage":"REDUCE COLLECT requires either fields(...) or fieldsAll() to be configured","messagePattern":"REDUCE COLLECT requires either fields\\(\\.\\.\\.\\) or fieldsAll\\(\\) to be configured","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/search/aggr/CollectReducer.java","lineNumber":140,"sourceCode":"  /** 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 {\n      args.add(fields.size());\n      args.addAll(fields);\n    }\n\n    if (!sortFields.isEmpty()) {\n      args.add(SearchKeyword.SORTBY);\n      args.add(sortFields.size() << 1); // 2 tokens per @field/ASC|DESC pair\n      for (SortedField sf : sortFields) {\n        args.add(sf.getField());\n        args.add(sf.getOrder());","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/search/aggr/CollectReducer.java#L122-L158","documentation":"When the CollectReducer serializes itself into command arguments (getOwnArgs), it requires a fields configuration: either explicit fields(...) or fieldsAll(). A REDUCE COLLECT with neither would produce a meaningless/unserverable FIELDS clause, so it throws this IllegalStateException at query build time.","triggerScenarios":"Adding a bare new CollectReducer() to an AggregationBuilder's reduce() without ever calling fields(...) or fieldsAll(), then executing the aggregation.","commonSituations":"Skeleton reducer left unconfigured during development; dynamic builders that skip field configuration when a list is empty; copy-pasted reducer code where the fields call was deleted.","solutions":["Call fields(\"@field1\", ...) or fieldsAll() on every CollectReducer before executing the query","Guard dynamic builders: if the field list is empty, either use fieldsAll() or skip adding the COLLECT reducer","Validate the aggregation builder in application code before sending (ensure each COLLECT reducer has fields set)"],"exampleFix":"// before\naggregationBuilder.reduce(new CollectReducer()); // IllegalStateException at build/send\n// after\naggregationBuilder.reduce(new CollectReducer().fieldsAll());\n// or\naggregationBuilder.reduce(new CollectReducer().fields(\"@title\", \"@tags\"));","handlingStrategy":"validation","validationCode":"// before sending the aggregation, verify every COLLECT reducer has fields\nif (!allFields && (fields == null || fields.isEmpty())) {\n  throw new IllegalStateException(\"CollectReducer needs fields(...) or fieldsAll()\");\n}","typeGuard":"null","tryCatchPattern":"try {\n  AggregationResult r = client.ftAggregate(indexName, aggregationBuilder);\n} catch (JedisException | IllegalStateException e) {\n  // reducer misconfiguration — fix builder before retry\n}","preventionTips":["Never add a bare new CollectReducer(); always finish configuration in the same expression","In dynamic builders, default empty field lists to fieldsAll() or skip the reducer","Validate the assembled AggregationBuilder before executing","Cover reducer construction with unit tests that assert the generated args"],"tags":["jedis","search","aggregation","reducer","missing-configuration"],"backgroundTag":"missing-required-config","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"}