apache/druid · error · IllegalArgumentException
Must provide at least one range
Error message
Must provide at least one range
What it means
ClusterByPartitions is a JSON-serialized list of ClusterByPartition ranges and must contain at least one range; an empty list is meaningless for partitioning. Its @JsonCreator constructor throws IAE when deserialized or constructed with an empty list.
Source
Thrown at processing/src/main/java/org/apache/druid/frame/key/ClusterByPartitions.java:49
/**
* Holder object for a set of {@link ClusterByPartition}. There are no preconditions put upon the partitions, except
* that there is at least one of them.
*
* In particular, they are not required to abut each other or to be non-overlapping. Use {@link #allAbutting()} to
* check if this particular list of partitions is in fact all abutting (and, therefore, also non-overlapping).
*/
public class ClusterByPartitions implements Iterable<ClusterByPartition>
{
private static final ClusterByPartitions ONE_UNIVERSAL_PARTITION =
new ClusterByPartitions(Collections.singletonList(new ClusterByPartition(null, null)));
private final List<ClusterByPartition> ranges;
@JsonCreator
public ClusterByPartitions(final List<ClusterByPartition> ranges)
{
if (ranges.isEmpty()) {
throw new IAE("Must provide at least one range");
}
this.ranges = ranges;
}
public static ClusterByPartitions oneUniversalPartition()
{
return ONE_UNIVERSAL_PARTITION;
}
/**
* Whether this list of partitions is all abutting, meaning: each partition's start is equal to the previous
* partition's end.
*
* Note that the start of the first partition, and the end of the last partition, may or may not be unbounded.
* So this list of partitions may not cover the entire space even if they are all abutting.
*/
public boolean allAbutting()View on GitHub (pinned to 9b90983fd2)
Solutions
- Provide at least one ClusterByPartition range in the spec, or use ClusterByPartitions.oneUniversalPartition() when a single all-encompassing partition is desired.
- Fix the upstream logic that generated the empty partitions list (it should fall back to a universal partition).
- Validate the JSON spec before submission: partitions array must be non-empty.
- If partitions are computed dynamically, guard: use oneUniversalPartition() when the computed list is empty.
Example fix
// before
new ClusterByPartitions(Collections.emptyList()); // IAE
// after
List<ClusterByPartition> ranges = computePartitions();
ClusterByPartitions p = ranges.isEmpty()
? ClusterByPartitions.oneUniversalPartition()
: new ClusterByPartitions(ranges); Defensive patterns
Strategy: validation
Validate before calling
if (ranges == null || ranges.isEmpty()) {
ranges = List.of(ClusterByPartition.universal()); // or oneUniversalPartition()
} Type guard
static boolean hasAtLeastOneRange(ClusterByPartitions p) {
return p != null && !p.ranges.isEmpty();
} Try / catch
try {
objectMapper.readValue(specJson, ClusterByPartitions.class);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("at least one range")) {
return ClusterByPartitions.oneUniversalPartition();
}
throw e;
} Prevention
- Use ClusterByPartitions.oneUniversalPartition() instead of an empty list when partitioning is effectively disabled.
- Validate partitioning JSON specs for a non-empty targetPartitions array before submission.
- Ensure partitioning passes emit a universal partition rather than nothing when they cannot split.
- Add JSON schema checks on spec files that embed ClusterByPartitions.
When it happens
Trigger: Deserializing a clustering/partitioning spec from JSON where the partitions array is [], or calling the constructor with Collections.emptyList() — e.g. a partitioning pass that produced no target ranges.
Common situations: MSQ query specs hand-edited or generated with an empty targetPartitions array; a partitioning job wrote an empty result that is then fed back as config; client code building specs dynamically from an empty set of partitions.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Invalid bucketByCount [%d]
- Cannot mix sortable and unsortable key columns
- DynamicPartitionsSpec must be used for best-effort rollup
- maxRetainedPartitionSketchBytes must be positive
- maxConcurrentStagesPerWorker must be >= 2 when pipelining
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/efdd8bdc0697395d.
Report an issue: GitHub.