{"record":{"id":"e98b762ce14c8b52","repo":"redis/jedis","slug":"aggregators-must-be-non-null-and-non-empty","errorCode":null,"errorMessage":"Aggregators must be non-null and non-empty","messagePattern":"Aggregators must be non-null and non-empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/timeseries/TSMRangeParams.java","lineNumber":158,"sourceCode":"      this.bucketDuration = 0;\n    }\n    return this;\n  }\n\n  /**\n   * Specifies multiple aggregators to be applied in a single {@code TS.MRANGE} / {@code TS.MREVRANGE} call. Aggregators are\n   * sent on the wire in the given order and the response values appear in the same order in {@link TSElement#getValues()}.\n   * Single-element arrays are accepted and behave like {@link #aggregation(AggregationType, long)}.\n   *\n   * @param aggregators ordered, non-empty list of aggregators\n   * @param bucketDuration aggregation bucket duration in milliseconds\n   * @return this\n   * @throws IllegalArgumentException if {@code aggregators} is empty\n   */\n  public TSMRangeParams aggregation(AggregationType[] aggregators, long bucketDuration) {\n    if (aggregators != null) {\n      if (aggregators.length == 0) {\n        throw new IllegalArgumentException(\"Aggregators must be non-null and non-empty\");\n      }\n      for (AggregationType a : aggregators) {\n        if (a == null) {\n          throw new IllegalArgumentException(\"Aggregators must not contain null elements\");\n        }\n      }\n      this.aggregators = aggregators;\n      this.bucketDuration = bucketDuration;\n    } else {\n      this.aggregators = null;\n      this.bucketDuration = 0;\n    }\n    return this;\n  }\n\n  /**\n   * This requires AGGREGATION.\n   */","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/timeseries/TSMRangeParams.java#L140-L176","documentation":"TSMRangeParams.aggregation(AggregationType[] aggregators, long bucketDuration) validates that when a non-null aggregators array is supplied it is non-empty and contains no null elements, since TS.RANGE/TS.MSEARCH aggregation requires at least one concrete aggregator. An empty array throws IllegalArgumentException(\"Aggregators must be non-null and non-empty\").","triggerScenarios":"Calling aggregation(new AggregationType[0], bucketDuration) or passing an empty array produced from an empty list/collection (e.g. aggregation(aggregatorList.toArray(new AggregationType[0]), 60000) with an empty list).","commonSituations":"Building range queries from user-selected aggregations where none were selected; config-driven dashboards where the aggregation list defaults to empty; refactors replacing the single AggregationType overload with the array overload but passing an empty array.","solutions":["Pass at least one AggregationType, e.g. aggregation(new AggregationType[]{AggregationType.AVG}, 60000).","Guard the call site: if the aggregator list is empty, skip setting aggregation instead of passing an empty array.","Validate user/config input to ensure at least one aggregation is selected when aggregation is intended."],"exampleFix":"// before\nparams.aggregation(aggList.toArray(new AggregationType[0]), 60000); // throws when empty\n// after\nif (!aggList.isEmpty()) {\n  params.aggregation(aggList.toArray(new AggregationType[0]), 60000);\n}","handlingStrategy":"validation","validationCode":"if (aggregators != null && aggregators.length == 0) {\n  throw new IllegalArgumentException(\"Provide at least one AggregationType\");\n}\nparams.aggregation(aggregators, bucketDuration);","typeGuard":"boolean hasAggregators(AggregationType[] a) {\n  return a != null && a.length > 0;\n}","tryCatchPattern":"try {\n  params.aggregation(aggs, bucketMs);\n} catch (IllegalArgumentException e) {\n  params = new TSMRangeParams(from, to); // proceed without aggregation\n  log.warn(\"Aggregation skipped: {}\", e.getMessage());\n}","preventionTips":["Only call aggregation(...) when at least one aggregator was selected.","Convert collections with toArray(new AggregationType[0]) and check isEmpty first.","Make aggregation an optional feature: empty selection means no aggregation clause, not an empty array."],"tags":["java","timeseries","validation"],"backgroundTag":"empty-required-field","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"}