apache/druid · error · IllegalArgumentException
maxConcurrentStagesPerWorker must be positive
Error message
maxConcurrentStagesPerWorker must be positive
What it means
maxConcurrentStages (maxConcurrentStagesPerWorker) must be at least 1; the constructor throws IAE when it is <= 0. A worker cannot run zero or negative concurrent stage slots, so this fails fast at kernel construction.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/kernel/controller/ControllerQueryKernelConfig.java:70
boolean pipeline,
boolean durableStorage,
boolean faultTolerance,
MSQDestination destination,
@Nullable String controllerHost,
@Nullable List<String> workerIds,
Map<String, Object> workerContextMap
)
{
if (maxRetainedPartitionSketchBytes <= 0) {
throw new IAE("maxRetainedPartitionSketchBytes must be positive");
}
if (pipeline && maxConcurrentStages < 2) {
throw new IAE("maxConcurrentStagesPerWorker must be >= 2 when pipelining");
}
if (maxConcurrentStages <= 0) {
throw new IAE("maxConcurrentStagesPerWorker must be positive");
}
if (pipeline && faultTolerance) {
throw new IAE("Cannot pipeline with fault tolerance");
}
if (pipeline && durableStorage) {
throw new IAE("Cannot pipeline with durable storage");
}
if (faultTolerance && !durableStorage) {
throw new IAE("Cannot have fault tolerance without durable storage");
}
this.maxRetainedPartitionSketchBytes = maxRetainedPartitionSketchBytes;
this.maxConcurrentStages = maxConcurrentStages;
this.pipeline = pipeline;
this.durableStorage = durableStorage;View on GitHub (pinned to 9b90983fd2)
Solutions
- Set maxConcurrentStages to a positive integer in the query context (default 2).
- If limiting concurrency, use 1 (with pipelining off) rather than 0.
- Guard programmatic construction: if (maxConcurrentStages <= 0) maxConcurrentStages = 2;
Example fix
// before
context.put("maxConcurrentStagesPerWorker", 0);
// after
context.put("maxConcurrentStagesPerWorker", 2); Defensive patterns
Strategy: validation
Validate before calling
if (maxConcurrentStages <= 0) {
throw new IllegalArgumentException("maxConcurrentStagesPerWorker must be >= 1");
} Try / catch
try {
kernelConfig = buildKernelConfig(ctx);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("must be positive")) {
ctx.put("maxConcurrentStagesPerWorker", 2);
kernelConfig = buildKernelConfig(ctx);
}
} Prevention
- Treat 0/negative tuning values as typos: clamp to >= 1 before submission.
- Validate numeric query-context values at submission time, not at controller runtime.
- Use named constants for defaults instead of literal 0.
When it happens
Trigger: Constructing ControllerQueryKernelConfig with maxConcurrentStages = 0 or negative, e.g. an unparsed/empty context value coerced to 0, or an invalid user-supplied value for maxConcurrentStagesPerWorker.
Common situations: Query context value 'maxConcurrentStagesPerWorker' set to 0 or a negative number by mistake; numeric parsing of empty string; bad tuning guidance copied into cluster defaults.
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
- maxRetainedPartitionSketchBytes must be positive
- maxConcurrentStagesPerWorker must be >= 2 when pipelining
- Cannot have fault tolerance without durable storage
- Invalid bucketByCount [%d]
- Cannot mix sortable and unsortable key columns
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/c3a84794f81c2a3d.
Report an issue: GitHub.