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
- Set maxPartitions to 1 when adjustable is true.
- Or set adjustable to false if you intend to keep a fixed maxPartitions > 1.
- 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
- Normalize adjustable specs to maxPartitions=1 in query-generation code.
- Don't mix user-supplied maxPartitions with engine-set adjustable flags.
- Add round-trip tests for shuffle spec serialization.
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
- Partition count must be at least 1
- ClusterBy key must be sortable
- Can't use both maxNumSubTasks and maxNumConcurrentSubTasks.
- Cannot have empty worker set
- Can not supply empty segments as input, please use either nu
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/ec618ab736e3bf6e.
Report an issue: GitHub.