apache/druid · error · IllegalArgumentException

Subtotal spec is either not a subset of top level…

Error message

Subtotal spec %s is either not a subset of top level dimensions.

What it means

GroupByQuery.verifySubtotalsSpec checks that each subtotal spec is a subset of the query's top-level dimensions. It throws IAE when a subtotal dimension cannot be found among the output names of the top-level dimension specs, meaning the subtotal references a non-existent or renamed dimension.

Solutions

  1. Change the subtotal spec to use the top-level dimensions' outputName values.
  2. Add the missing dimension to the top-level dimensionSpecs, or align outputName with the subtotal name.
  3. Validate subtotals against dimension output names in query-building code before constructing the query.

Example fix

// before
dimensions: [new DefaultDimensionSpec("col", "alias")], subtotals: [["col"]]
// after
dimensions: [new DefaultDimensionSpec("col", "alias")], subtotals: [["alias"]]
Defensive patterns

Strategy: validation

Validate before calling

Set<String> dims = query.getDimensions().stream().map(DimensionSpec::getOutputName).collect(Collectors.toSet());
boolean valid = query.getSubtotalsSpec().stream().allMatch(sub -> dims.containsAll(sub));

Try / catch

try { GroupByQuery q = builder.build(); } catch (IllegalArgumentException e) { /* fix subtotals to use outputNames */ }

Prevention

When it happens

Trigger: Building or deserializing a GroupByQuery with subtotals containing a dimension name that is not in the top-level dimensionSpecs output names (including missing outputName aliases).

Common situations: SQL planning producing subtotals after dimension renaming; hand-written native queries where subtotal uses the underlying column name instead of the alias set via outputName.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/2a1ba06718dd38db. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/groupby/GroupByQuery.java:269

  @Nullable
  private List<List<String>> verifySubtotalsSpec(
      @Nullable List<List<String>> subtotalsSpec,
      List<DimensionSpec> dimensions
  )
  {
    // if subtotalsSpec exists then validate that all are subsets of dimensions spec.
    if (subtotalsSpec != null) {
      for (List<String> subtotalSpec : subtotalsSpec) {
        for (String s : subtotalSpec) {
          boolean found = false;
          for (DimensionSpec ds : dimensions) {
            if (s.equals(ds.getOutputName())) {
              found = true;
              break;
            }
          }
          if (!found) {
            throw new IAE(
                "Subtotal spec %s is either not a subset of top level dimensions.",
                subtotalSpec
            );
          }
        }
      }
    }

    return subtotalsSpec;
  }

  @JsonProperty
  @Override
  @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = VirtualColumns.JsonIncludeFilter.class)
  public VirtualColumns getVirtualColumns()
  {
    return virtualColumns;
  }

View on GitHub (pinned to 9b90983fd2)