{"record":{"id":"4822a15f8bf980e8","repo":"apache/druid","slug":"expected-d-tasks-to-succeed-but-we-got-d-su","errorCode":null,"errorMessage":"Expected [%d] tasks to succeed, but we got [%d] succeeded tasks and [%d] failed tasks","messagePattern":"Expected \\[(.+?)\\] tasks to succeed, but we got \\[(.+?)\\] succeeded tasks and \\[(.+?)\\] failed tasks","errorType":"exception","errorClass":"ISE","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexPhaseRunner.java","lineNumber":167,"sourceCode":"          final TaskState completeState = taskCompleteEvent.getLastState();\n          getSubtaskCompletionCallback(taskCompleteEvent).run();\n          switch (completeState) {\n            case SUCCESS:\n              final TaskStatusPlus completeStatus = taskCompleteEvent.getLastStatus();\n              if (completeStatus == null) {\n                throw new ISE(\"Last status of complete task is missing!\");\n              }\n              if (!subTaskSpecIterator.hasNext()) {\n                // We have no more subTasks to run\n                if (taskMonitor.getNumRunningTasks() == 0 && taskCompleteEvents.isEmpty()) {\n                  subTaskScheduleAndMonitorStopped = true;\n                  if (subTaskSpecIterator.count == taskMonitor.getNumSucceededTasks()) {\n                    // Succeeded\n                    state = TaskState.SUCCESS;\n                  } else {\n                    // Failed\n                    final ParallelIndexingPhaseProgress monitorStatus = taskMonitor.getProgress();\n                    throw new ISE(\n                        \"Expected [%d] tasks to succeed, but we got [%d] succeeded tasks and [%d] failed tasks\",\n                        subTaskSpecIterator.count,\n                        monitorStatus.getSucceeded(),\n                        monitorStatus.getFailed()\n                    );\n                  }\n                }\n              } else if (taskMonitor.getNumRunningTasks() < maxNumConcurrentSubTasks) {\n                // We have more subTasks to run\n                submitNewTask(taskMonitor, subTaskSpecIterator.next());\n              } else {\n                // We have more subTasks to run, but don't have enough available task slots\n                // do nothing\n              }\n              break;\n            case FAILED:\n              // TaskMonitor already tried everything it can do for failed tasks. We failed.\n              state = TaskState.FAILED;","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexPhaseRunner.java#L149-L185","documentation":"Thrown when all subtasks finished (none running, no pending completion events) but the number of succeeded subtasks does not equal the number of subtask specs that were submitted. Parallel index tasks require every spec's subtask to succeed; any failure or missing success makes the whole phase fail.","triggerScenarios":"One or more subtasks of a ParallelIndexTask fail (e.g. bad input splits, oversized segments, worker losses) so numSucceededTasks < subTaskSpecIterator.count while the phase winds down.","commonSituations":"Subtasks hitting out-of-memory or row-too-large errors; workers killed during rebalancing; replace-mode tasks whose intervals were trimmed so some subtasks had no data; retryable subtask failures exhausting maxRetry.","solutions":["Inspect the failed subtasks' logs via the overlord UI to find the root-cause failure and fix the input/tuning config.","Increase maxNumConcurrentSubTasks / maxRetry in ParallelIndexTuningConfig so transient failures are retried.","Fix the underlying data problem (bad rows, huge splits) — lower splitHintSpec targetPartitionSize or filter bad input files.","Re-run the ingestion task after fixing; successful partial work is discarded for this task run."],"exampleFix":"// before\n// tuningConfig: { \"type\": \"parallel_index\", \"maxNumSubTasks\": 4 }\n// after: allow retries for transient subtask failures\n// tuningConfig: { \"type\": \"parallel_index\", \"maxNumSubTasks\": 4, \"maxRetry\": 3 }","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (ISE e) {\n  if (e.getMessage().startsWith(\"Expected [\")) {\n    // inspect failed subtask specs via /subtaskspecs?state=FAILED, fix root cause, resubmit task\n  }\n}","preventionTips":["Set maxRetry > 0 in ParallelIndexTuningConfig for transient failures","Pre-validate input files/splits before submitting","Monitor subtask logs for OOM/oversize segment errors","Size splits with splitHintSpec so no subtask is overloaded"],"tags":["parallel-ingestion","subtask-failure","batch-ingestion"],"backgroundTag":"invalid-state-transition","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"}