{"record":{"id":"b5c57d9ecd7ac1d2","repo":"apache/druid","slug":"at-least-one-task-runner-must-be-enabled","errorCode":null,"errorMessage":"At least one task runner must be enabled","messagePattern":"At least one task runner must be enabled","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/MultipleKubernetesTaskRunnerFactory.java","lineNumber":121,"sourceCode":"    this.dynamicConfigSupplier = dynamicConfigSupplier;\n    this.configManager = configManager;\n    this.taskConfig = taskConfig;\n    this.startupLoggingConfig = startupLoggingConfig;\n    this.druidNode = druidNode;\n    this.properties = properties;\n    this.httpClientFactory = httpClientFactory;\n  }\n\n  @Override\n  public TaskRunner build()\n  {\n    final List<MultipleKubernetesTaskRunnerConfig.KubernetesCluster> enabledClusters = this.runnerConfig.getClusters()\n                                                                                                        .stream()\n                                                                                                        .filter(cluster -> !cluster.isDisabled())\n                                                                                                        .collect(Collectors.toList());\n\n    if (enabledClusters.isEmpty()) {\n      throw new IllegalArgumentException(\"At least one task runner must be enabled\");\n    }\n\n    final String adapter = getAdapterType();\n    final boolean requiresOverlordPodSource = requiresOverlordPodSource(adapter);\n    final String overlordPodSourceNamespace = requiresOverlordPodSource\n                                              ? getOverlordPodSourceNamespace(enabledClusters)\n                                              : null;\n    DruidKubernetesClient overlordPodSourceClient = null;\n    AutoscalableThreadPoolExecutor sharedExecutor = null;\n    final List<MultipleKubernetesTaskRunnerDelegate> taskRunners = new ArrayList<>();\n\n    try {\n      overlordPodSourceClient = requiresOverlordPodSource\n                                ? createOverlordPodSourceClient(overlordPodSourceNamespace)\n                                : null;\n      final int totalCapacity = new KubernetesTaskRunnerEffectiveConfig(this.runnerConfig, this.dynamicConfigSupplier)\n          .getCapacity();\n      sharedExecutor = new AutoscalableThreadPoolExecutor(totalCapacity, this.configManager);","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/MultipleKubernetesTaskRunnerFactory.java#L103-L139","documentation":"MultipleKubernetesTaskRunnerFactory.build() throws this IllegalArgumentException when the runner configuration defines no enabled Kubernetes clusters - every configured cluster has disabled=true, or the clusters list is empty. The multi-cluster runner needs at least one active cluster to dispatch tasks to.","triggerScenarios":"All entries in the multi-cluster config set disabled: true; an empty clusters list supplied to the factory; a config-filtering step (e.g. selecting clusters by label) that excludes everything.","commonSituations":"Operators disabling a cluster for maintenance and forgetting at least one remains; migrating from single-cluster config where the new clusters block was left empty; typo'd property names so the clusters list parses as empty.","solutions":["Enable at least one cluster (set disabled: false) in druid.indexer.runner.k8s.clusters","Add a valid cluster entry with k8sHost/credentials if the list is empty","Verify the config property path so clusters actually parse into the runnerConfig","If intentionally disabling all clusters, disable the multi-runner itself rather than its clusters"],"exampleFix":"// before\ndruid.indexer.runner.k8s.clusters=[{\"name\":\"c1\",\"disabled\":true}]\n// after\ndruid.indexer.runner.k8s.clusters=[{\"name\":\"c1\",\"disabled\":false}]","handlingStrategy":"validation","validationCode":"List<Cluster> clusters = runnerConfig.getClusters();\nboolean anyEnabled = clusters != null && clusters.stream().anyMatch(c -> !c.isDisabled());\nif (!anyEnabled) { throw new IllegalArgumentException(\"enable at least one k8s cluster\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at least one cluster enabled at all times","Validate cluster config at deploy time before Overlord startup","Confirm property keys parse into the clusters list (watch for typos yielding empty lists)"],"tags":["configuration","kubernetes","overlord","multi-cluster","validation"],"backgroundTag":"missing-required-config","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}