elastic/elasticsearch · error · IllegalArgumentException

Aggregator [{name}] of type [{getType()}] cannot accept sub-

Error message

Aggregator [{name}] of type [{getType()}] cannot accept sub-aggregations

What it means

Thrown by the LeafOnly clone constructor of ArrayValuesSourceAggregationBuilder when factoriesBuilder.count() > 0 — i.e., during a rewrite/clone the builder discovers it has sub-aggregations attached. LeafOnly aggregations (multi-field variants of metrics like matrix_stats) produce a single metric value and cannot have sub-aggregations nested under them, so attaching any is a structural error caught at rewrite time.

Source

Thrown at modules/aggregations/src/main/java/org/elasticsearch/aggregations/metric/ArrayValuesSourceAggregationBuilder.java:48

import java.util.Objects;

public abstract class ArrayValuesSourceAggregationBuilder<AB extends ArrayValuesSourceAggregationBuilder<AB>> extends
    AbstractAggregationBuilder<AB> {

    public static final ParseField MULTIVALUE_MODE_FIELD = new ParseField("mode");

    public abstract static class LeafOnly<AB extends ArrayValuesSourceAggregationBuilder<AB>> extends ArrayValuesSourceAggregationBuilder<
        AB> {

        protected LeafOnly(String name) {
            super(name);
        }

        @SuppressWarnings("this-escape")
        protected LeafOnly(LeafOnly<AB> clone, Builder factoriesBuilder, Map<String, Object> metadata) {
            super(clone, factoriesBuilder, metadata);
            if (factoriesBuilder.count() > 0) {
                throw new IllegalArgumentException("Aggregator [" + name + "] of type [" + getType() + "] cannot accept sub-aggregations");
            }
        }

        /**
         * Read from a stream
         */
        protected LeafOnly(StreamInput in) throws IOException {
            super(in);
        }

        @Override
        public AB subAggregations(Builder subFactories) {
            throw new IllegalArgumentException("Aggregator [" + name + "] of type [" + getType() + "] cannot accept sub-aggregations");
        }

        @Override
        public final BucketCardinality bucketCardinality() {
            return BucketCardinality.NONE;

View on GitHub (pinned to db6a809a66)

Solutions

  1. Remove the sub-aggregations from the LeafOnly metric — move them to a parent bucket aggregation if needed.
  2. Check the aggregation type's documentation: metric aggregations like matrix_stats are leaf-only and cannot nest sub-aggregations.
  3. Restructure so the metric is a sibling, not a parent, of the sub-aggregation.

Example fix

// before: sub-aggregation nested under a leaf-only metric
{"matrix_stats":{"fields":["a","b"],"aggs":{"sub":{"avg":{"field":"c"}}}}}
// after: make them siblings
{"aggs":{"m":{"matrix_stats":{"fields":["a","b"]}},"sub":{"avg":{"field":"c"}}}}
Defensive patterns

Strategy: type-guard

Validate before calling

if (agg instanceof ArrayValuesSourceAggregationBuilder.LeafOnly<?> && subFactories.count() > 0) {
  throw new IllegalArgumentException("leaf-only aggregation cannot have sub-aggregations");
}

Type guard

boolean isLeafOnly(org.elasticsearch.search.aggregations.AggregationBuilder b) {
  return b instanceof ArrayValuesSourceAggregationBuilder.LeafOnly<?>;
}

Prevention

When it happens

Trigger: Calling .subAggregations(...)/.addAggregation(...) on a LeafOnly aggregation (or constructing one with a non-empty factories builder) and then triggering rewrite (e.g. via build() or the search execution path). The error surfaces during the clone-with-rewrite step rather than at the moment of attachment because the constructor path is the one that validates.

Common situations: Users nesting a sub-aggregation under a metric that does not support it (e.g. under matrix_stats). Programmatic builders that generically attach sub-aggregations to any aggregation type. REST requests with a `aggs` block nested inside a leaf-only metric.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/8b95ccbda3720ce6. Report an issue: GitHub.