apache/druid · error · RuntimeException

taskCountMin <= taskCountStart <= taskCountMax

Error message

taskCountMin <= taskCountStart <= taskCountMax

What it means

LagBasedAutoScalerConfig also validates an optional taskCountStart: when autoscaling is enabled and taskCountStart is provided, it must lie within the [taskCountMin, taskCountMax] range. A start value outside this window makes the initial task count unreachable by the scaler, so the config throws this RuntimeException.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/LagBasedAutoScalerConfig.java:103

    this.lagCollectionIntervalMillis = lagCollectionIntervalMillis != null ? lagCollectionIntervalMillis : 30000;
    this.lagCollectionRangeMillis = lagCollectionRangeMillis != null ? lagCollectionRangeMillis : 600000;
    this.scaleActionStartDelayMillis = scaleActionStartDelayMillis != null ? scaleActionStartDelayMillis : 300000;
    this.scaleActionPeriodMillis = scaleActionPeriodMillis != null ? scaleActionPeriodMillis : 60000;
    this.scaleOutThreshold = scaleOutThreshold != null ? scaleOutThreshold : 6000000;
    this.scaleInThreshold = scaleInThreshold != null ? scaleInThreshold : 1000000;
    this.triggerScaleOutFractionThreshold = triggerScaleOutFractionThreshold != null ? triggerScaleOutFractionThreshold : 0.3;
    this.triggerScaleInFractionThreshold = triggerScaleInFractionThreshold != null ? triggerScaleInFractionThreshold : 0.9;
    this.lagAggregate = lagAggregate;

    // Only do taskCountMax and taskCountMin check when autoscaler is enabled. So that users left autoConfig empty{} will not throw any exception and autoscaler is disabled.
    // If autoscaler is disabled, no matter what configs are set, they are not used.
    if (this.enableTaskAutoScaler) {
      if (taskCountMax == null || taskCountMin == null) {
        throw new RuntimeException("taskCountMax or taskCountMin can't be null!");
      } else if (taskCountMax < taskCountMin) {
        throw new RuntimeException("taskCountMax can't lower than taskCountMin!");
      } else if (taskCountStart != null && (taskCountStart > taskCountMax || taskCountStart < taskCountMin)) {
        throw new RuntimeException("taskCountMin <= taskCountStart <= taskCountMax");
      }
      this.taskCountMax = taskCountMax;
      this.taskCountMin = taskCountMin;
      this.taskCountStart = taskCountStart;
    }

    this.scaleInStep = scaleInStep != null ? scaleInStep : 1;
    this.scaleOutStep = scaleOutStep != null ? scaleOutStep : 2;
    this.minTriggerScaleActionFrequencyMillis =
        minTriggerScaleActionFrequencyMillis != null ? minTriggerScaleActionFrequencyMillis : 600000;
    this.minScaleUpDelay = Configs.valueOrDefault(minScaleUpDelay, Duration.millis(this.minTriggerScaleActionFrequencyMillis));
    this.minScaleDownDelay = Configs.valueOrDefault(minScaleDownDelay, Duration.millis(this.minTriggerScaleActionFrequencyMillis));

    Preconditions.checkArgument(
        stopTaskCountRatio == null || (stopTaskCountRatio > 0.0 && stopTaskCountRatio <= 1.0),
        "0.0 < stopTaskCountRatio <= 1.0"
    );
    Preconditions.checkArgument(

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Adjust taskCountStart so taskCountMin <= taskCountStart <= taskCountMax
  2. Remove taskCountStart (it is optional; taskCountMin is then used as the starting count)
  3. Widen taskCountMin/taskCountMax to include the desired start value

Example fix

// before
"taskCountMin": 1,
"taskCountMax": 3,
"taskCountStart": 6
// after
"taskCountMin": 1,
"taskCountMax": 6,
"taskCountStart": 6
Defensive patterns

Strategy: validation

Validate before calling

if (cfg.taskCountStart != null) {
  if (cfg.taskCountStart > cfg.taskCountMax || cfg.taskCountStart < cfg.taskCountMin) throw new IllegalArgumentException("taskCountMin <= taskCountStart <= taskCountMax required");
}

Try / catch

try { supervisor.start(spec); } catch (RuntimeException e) { if (e.getMessage().equals("taskCountMin <= taskCountStart <= taskCountMax")) { resubmitWithClampedStart(); } else { throw e; } }

Prevention

When it happens

Trigger: Constructing LagBasedAutoScalerConfig with enableTaskAutoScaler=true, a non-null taskCountStart, and either taskCountStart > taskCountMax or taskCountStart < taskCountMin.

Common situations: Setting taskCountStart to the current task count after manually scaling, then changing min/max; typos in start; reusing a start value across supervisors with different ranges.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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