apache/druid · error · IllegalArgumentException

Partition count must be at least 1

Error message

Partition count must be at least 1

What it means

GlobalSortMaxCountShuffleSpec partitions output by a global sort with a maximum partition count. maxPartitions must be >= 1; values below 1 make no sense as a partition count, so the constructor throws IAE.

Source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/kernel/GlobalSortMaxCountShuffleSpec.java:65

  private final boolean adjustable;

  @JsonCreator
  public GlobalSortMaxCountShuffleSpec(
      @JsonProperty("clusterBy") final ClusterBy clusterBy,
      @JsonProperty("partitions") final int maxPartitions,
      @JsonProperty("aggregate") final boolean aggregate,
      @JsonProperty("limitHint") final Long limitHint,
      @JsonProperty("adjustable") final boolean adjustable
  )
  {
    this.clusterBy = Preconditions.checkNotNull(clusterBy, "clusterBy");
    this.maxPartitions = maxPartitions;
    this.aggregate = aggregate;
    this.limitHint = limitHint == null ? UNLIMITED : limitHint;
    this.adjustable = adjustable;

    if (maxPartitions < 1) {
      throw new IAE("Partition count must be at least 1");
    }

    if (adjustable && maxPartitions != 1) {
      throw new IAE("Partition count must be 1 when adjustable is true, but was [%d]", maxPartitions);
    }

    if (!clusterBy.sortable()) {
      throw new IAE("ClusterBy key must be sortable");
    }

    if (clusterBy.getBucketByCount() > 0) {
      // Only GlobalSortTargetSizeShuffleSpec supports bucket-by.
      throw new IAE("Cannot bucket with %s partitioning", TYPE);
    }
  }

  public GlobalSortMaxCountShuffleSpec(
      final ClusterBy clusterBy,

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Set maxPartitions to a positive value (at least 1) in the shuffle spec / query JSON.
  2. Fix the code computing maxNumPartitions to clamp to a minimum of 1 (e.g. Math.max(1, computed)).
  3. Check MSQ context parameters (e.g. maxPartitions / limit settings) that feed this value.

Example fix

// before
int maxPartitions = workers.size(); // can be 0
// after
int maxPartitions = Math.max(1, workers.size());
Defensive patterns

Strategy: validation

Validate before calling

if (maxPartitions < 1) {
  throw new IllegalArgumentException("maxPartitions must be >= 1, got " + maxPartitions);
}
new GlobalSortMaxCountShuffleSpec(clusterBy, maxPartitions, aggregate, limitHint, adjustable);

Try / catch

try {
  spec = objectMapper.readValue(json, GlobalSortMaxCountShuffleSpec.class);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().equals("Partition count must be at least 1")) {
    // clamp and rebuild with maxPartitions = 1
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Constructing GlobalSortMaxCountShuffleSpec (directly or via JSON deserialization of an MSQ task) with maxPartitions = 0 or negative - typically from a computed limit like maxNumPartitions derived from an empty/zero worker count or unset config.

Common situations: Query-generation code computing partition count as workers.size() when no workers are known; clients hand-writing shuffle spec JSON with 0; numeric truncation bugs turning small fractions into 0.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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