apache/druid · error · RuntimeException

taskCountMax or taskCountMin can't be null!

Error message

taskCountMax or taskCountMin can't be null!

What it means

LagBasedAutoScalerConfig validates that when the task autoscaler is enabled, taskCountMax and taskCountMin must be provided (and Max >= Min, Start within range). A plain RuntimeException is thrown when either is null, because the autoscaler cannot function without its scaling bounds. Leaving autoscaler disabled (empty autoConfig) bypasses this check.

Source

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

          @Nullable @JsonProperty("stopTaskCountRatio") Double stopTaskCountRatio
  )
  {
    this.enableTaskAutoScaler = enableTaskAutoScaler != null ? enableTaskAutoScaler : false;
    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(

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Add both taskCountMax and taskCountMin to autoScalerConfig, with taskCountMax >= taskCountMin.
  2. If you don't want autoscaling, set "autoScalerConfig": {} (or omit enableTaskAutoScaler) so the check is skipped.
  3. Verify property names/casing in the spec so Jackson populates the fields rather than leaving them null.

Example fix

// before
"autoScalerConfig": {
  "enableTaskAutoScaler": true,
  "taskCountMax": 4
}
// after: provide both bounds
"autoScalerConfig": {
  "enableTaskAutoScaler": true,
  "taskCountMin": 1,
  "taskCountMax": 4,
  "taskCountStart": 2
}
Defensive patterns

Strategy: validation

Validate before calling

if (autoScalerConfig.enableTaskAutoScaler &&
    (autoScalerConfig.taskCountMax == null || autoScalerConfig.taskCountMin == null)) {
    throw new IllegalArgumentException("taskCountMax and taskCountMin required when autoscaler enabled");
}

Try / catch

try { buildConfig(spec); } catch (RuntimeException e) { if (e.getMessage().contains("taskCountMax or taskCountMin")) { applyDefaultBounds(); } }

Prevention

When it happens

Trigger: Constructing the config (e.g. from a supervisor spec's autoScalerConfig with enableTaskAutoScaler: true) where taskCountMax or taskCountMin is missing/null.

Common situations: Spec with "autoScalerConfig": {"enableTaskAutoScaler": true} but forgotten taskCountMax/taskCountMin; typo in property names; templated spec omitting the bounds; JSON casing mismatch so fields deserialized as null.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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