apache/druid · error · IllegalArgumentException

Partition count must be 1 when adjustable is true, but was [

Error message

Partition count must be 1 when adjustable is true, but was [%d]

What it means

An adjustable GlobalSortMaxCountShuffleSpec lets the engine change the partition count during execution, and by definition it must be capped at a single partition. If adjustable is true but maxPartitions != 1, the constructor rejects the combination with IAE.

Source

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

      @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,
      final int maxPartitions,
      final boolean aggregate,
      final Long limitHint
  )

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Set maxPartitions to 1 when adjustable is true.
  2. Or set adjustable to false if you intend to keep a fixed maxPartitions > 1.
  3. Fix query-generation code to normalize adjustable specs to maxPartitions=1.

Example fix

// before
new GlobalSortMaxCountShuffleSpec(clusterBy, 4, false, true, true); // adjustable with 4
// after
new GlobalSortMaxCountShuffleSpec(clusterBy, 1, false, true, true);
Defensive patterns

Strategy: validation

Validate before calling

if (adjustable && maxPartitions != 1) {
  maxPartitions = 1; // adjustable specs must be capped at 1
}
new GlobalSortMaxCountShuffleSpec(clusterBy, maxPartitions, aggregate, limitHint, adjustable);

Try / catch

try {
  spec = buildShuffleSpec(...);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Partition count must be 1 when adjustable")) {
    spec = buildShuffleSpec(... maxPartitions = 1 ...);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Creating the spec with adjustable=true and maxPartitions set to any value other than 1, either via direct construction or JSON like {"type":"maxCountSorting","maxPartitions":4,"adjustable":true}.

Common situations: Query builders that set adjustable automatically while preserving a user-supplied maxPartitions; hand-written task JSON combining both fields inconsistently; conversion bugs between shuffle spec types during SQL-to-native translation.

Related errors


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