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
HashShuffleSpec with adjustable=true means the controller may re-shard at runtime starting from a single partition, so the constructor requires numPartitions == 1. Passing adjustable=true with any other partition count violates that contract and throws IAE. Adjustable hash shuffles must seed with exactly one partition.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/kernel/HashShuffleSpec.java:50
public static final String TYPE = "hash";
private final ClusterBy clusterBy;
private final int numPartitions;
private final boolean adjustable;
@JsonCreator
public HashShuffleSpec(
@JsonProperty("clusterBy") final ClusterBy clusterBy,
@JsonProperty("partitions") final int numPartitions,
@JsonProperty("adjustable") final boolean adjustable
)
{
this.clusterBy = clusterBy;
this.numPartitions = numPartitions;
this.adjustable = adjustable;
if (adjustable && numPartitions != 1) {
throw new IAE("Partition count must be 1 when adjustable is true, but was [%d]", numPartitions);
}
if (clusterBy.getBucketByCount() > 0) {
// Only GlobalSortTargetSizeShuffleSpec supports bucket-by.
throw new IAE("Cannot bucket with %s partitioning (clusterBy = %s)", TYPE, clusterBy);
}
}
@Override
public ShuffleKind kind()
{
return clusterBy.sortable() && !clusterBy.isEmpty() ? ShuffleKind.HASH_LOCAL_SORT : ShuffleKind.HASH;
}
@Override
@JsonProperty
public ClusterBy clusterBy()
{View on GitHub (pinned to 9b90983fd2)
Solutions
- Set numPartitions to 1 when adjustable is true, letting the controller grow partitions dynamically
- Set adjustable to false if a fixed numPartitions > 1 is genuinely required
- Audit the call site (ShuffleSpecFactory.create) so the partition count passed for adjustable shuffles is always 1
Example fix
// before new HashShuffleSpec(clusterBy, 4, true); // after new HashShuffleSpec(clusterBy, 1, true); // adjustable: start at 1 // or, for fixed 4 partitions new HashShuffleSpec(clusterBy, 4, false);
Defensive patterns
Strategy: validation
Validate before calling
if (adjustable && numPartitions != 1) {
throw new IllegalArgumentException("Adjustable hash shuffles must start with numPartitions = 1");
} Type guard
static boolean validHashSpecParams(int numPartitions, boolean adjustable) {
return !adjustable || numPartitions == 1;
} Try / catch
try {
spec = new HashShuffleSpec(clusterBy, numPartitions, adjustable);
} catch (IllegalArgumentException e) {
spec = new HashShuffleSpec(clusterBy, 1, adjustable); // or set adjustable=false
} Prevention
- Start adjustable shuffles at 1 partition and let the controller scale
- Set adjustable=false when a fixed partition count > 1 is required
- Centralize shuffle construction in ShuffleSpecFactory to keep these invariants in one place
When it happens
Trigger: Constructing HashShuffleSpec(clusterBy, numPartitions, adjustable=true) where numPartitions != 1 — e.g. ShuffleSpecFactory.create for HASH kind with adjustable workers config and a partition count > 1.
Common situations: Query context settings that both set an explicit multi-partition count and enable adjustable partitioning (e.g. dynamic worker scaling with fixed partitions); miswired factory parameters.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot bucket with %s partitioning
- ClusterBy key must be sortable
- Cannot bucket with %s partitioning (clusterBy = %s)
- Partition count must be at least 1
- Partition count must be 1 when adjustable is true, but was [
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6d95e10e216e5a6e.
Report an issue: GitHub.