redis/jedis · error · IllegalArgumentException
Aggregators must not contain null elements
Error message
Aggregators must not contain null elements
What it means
TSNRangeParams.aggregation(AggregationType[], long) rejects null elements inside the aggregators array with IllegalArgumentException("Aggregators must not contain null elements"), wrapping each entry into a per-key single-element array; a null entry would generate an invalid command, so it is rejected during parameter construction.
Solutions
- Filter nulls before the call: Arrays.stream(arr).filter(Objects::nonNull).toArray(AggregationType[]::new).
- Use exact-size collections converted with toArray(new AggregationType[0]) instead of pre-sized arrays.
- Make the config parser reject unknown aggregator names instead of silently mapping them to null.
Example fix
// before AggregationType[] a = new AggregationType[2]; a[0] = AggregationType.MIN; node.aggregation(a, 60000); // null element -> throws // after List<AggregationType> a = new ArrayList<>(); a.add(AggregationType.MIN); node.aggregation(a.toArray(new AggregationType[0]), 60000);
Defensive patterns
Strategy: validation
Validate before calling
AggregationType[] cleaned = Arrays.stream(aggs).filter(Objects::nonNull).toArray(AggregationType[]::new); node.aggregation(cleaned.length > 0 ? cleaned : null, bucketDuration);
Type guard
boolean noNullElements(AggregationType[] a) {
return a == null || Arrays.stream(a).noneMatch(Objects::isNull);
} Try / catch
try {
node.aggregation(aggs, bucketMs);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("null elements")) {
throw new IllegalStateException("Unmapped aggregator name in config produced null; fix the enum parsing", e);
}
throw e;
} Prevention
- Sanitize external arrays with Objects::nonNull filtering before passing to aggregation.
- Avoid pre-sized arrays with unfilled slots; use growable lists.
- Make config parsing of AggregationType fail loudly on unknown names rather than returning null.
When it happens
Trigger: Passing an array containing nulls, typically from pre-sized partially filled arrays (new AggregationType[n]) or from lists deserialized from config where unknown aggregator names became null.
Common situations: Building per-key aggregator arrays with placeholder null slots; YAML/JSON config mapping unrecognized aggregation names to null; merging multiple sources of aggregator settings where some are absent.
Related errors
- Aggregators must not contain null elements
- Aggregators must not contain null elements
- DriverInfo must not be null
- Aggregators must be non-null and non-empty
- FILTER arguments must be set.
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/de0e97245cf8de40.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/timeseries/TSNRangeParams.java:140
* is emitted as its own {@code AGGREGATION} token.
* @param aggregators ordered, non-empty list holding one aggregator per key
* @param bucketDuration aggregation bucket duration in milliseconds
* @return this
* @throws IllegalArgumentException if {@code aggregators} is empty or contains a null element
*/
public TSNRangeParams aggregation(AggregationType[] aggregators, long bucketDuration) {
if (aggregators == null) {
this.aggregators = null;
this.bucketDuration = 0;
return this;
}
if (aggregators.length == 0) {
throw new IllegalArgumentException("Aggregators must be non-null and non-empty");
}
AggregationType[][] perKey = new AggregationType[aggregators.length][];
for (int i = 0; i < aggregators.length; i++) {
if (aggregators[i] == null) {
throw new IllegalArgumentException("Aggregators must not contain null elements");
}
perKey[i] = new AggregationType[] { aggregators[i] };
}
this.aggregators = perKey;
this.bucketDuration = bucketDuration;
return this;
}
/**
* Applies one or more aggregators per key, in key order. The outer array length must equal the
* number of keys sent to the command (the server rejects a mismatch); each inner array holds the
* aggregators for that key and is emitted as a single comma-joined {@code AGGREGATION} token
* (e.g. {@code AVG,MAX}). The response returns one value column per aggregator, flattened in key
* then aggregator order.
* @param aggregators ordered, non-empty per-key lists of aggregators
* @param bucketDuration aggregation bucket duration in milliseconds
* @return this
* @throws IllegalArgumentException if {@code aggregators} (or any inner array) is empty orView on GitHub (pinned to 6dac31d4c2)