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

  1. Filter nulls before the call: Arrays.stream(arr).filter(Objects::nonNull).toArray(AggregationType[]::new).
  2. Use exact-size collections converted with toArray(new AggregationType[0]) instead of pre-sized arrays.
  3. 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

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


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 or

View on GitHub (pinned to 6dac31d4c2)