{"record":{"id":"557cca90729fa900","repo":"apache/druid","slug":"work-order-not-present-for-stage-s","errorCode":null,"errorMessage":"Work order not present for stage[%s]","messagePattern":"Work order not present for stage\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/kernel/controller/ControllerQueryKernel.java","lineNumber":590,"sourceCode":"  }\n\n  /**\n   * Delegates call to {@link ControllerStageTracker#getResultObject()}\n   */\n  public Object getResultObjectForStage(final StageId stageId)\n  {\n    return getStageTrackerOrThrow(stageId).getResultObject();\n  }\n\n  /**\n   * Checks if the stage can be started, delegates call to {@link ControllerStageTracker#start()} for internal phase\n   * transition and registers the transition in this queryKernel. Work orders need to be created via\n   * {@link ControllerQueryKernel#createWorkOrders(int, int, Int2ObjectMap)} before calling this method.\n   */\n  public void startStage(final StageId stageId)\n  {\n    if (stageWorkOrders.get(stageId) == null) {\n      throw new ISE(\"Work order not present for stage[%s]\", stageId);\n    }\n\n    doWithStageTracker(stageId, stageTracker -> {\n      if (stageTracker.getPhase() != ControllerStagePhase.NEW) {\n        throw new ISE(\"Cannot start the stage: [%s]\", stageId);\n      }\n\n      stageTracker.start();\n    });\n  }\n\n  /**\n   * Checks if the stage can be finished, delegates call to {@link ControllerStageTracker#finish()} for internal phase\n   * transition and registers the transition in this query kernel\n   * <p>\n   * If the method is called with strict = true, we confirm if the stage can be marked as finished or else\n   * throw illegal argument exception\n   */","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/kernel/controller/ControllerQueryKernel.java#L572-L608","documentation":"Thrown by ControllerQueryKernel.startStage as an IllegalStateException when the kernel's stageWorkOrders map contains no entry for the given StageId. The kernel requires createWorkOrders(...) to have populated work orders for the stage before startStage is called, since starting a stage means handing those work orders to workers.","triggerScenarios":"Calling startStage(stageId) before createWorkOrders(stageNumber, maxWorkerCount, workerOrders) has run for that stage, or after the work orders were removed (e.g. by a prior finishStage). Also reachable via startWorkForStage when the controller state machine is out of order or the kernel was reloaded/restored from a snapshot that lacks the work orders.","commonSituations":"Controller failover/restart replaying the state machine with a kernel snapshot that predates work-order creation; custom or patched controller logic invoking startStage manually; race conditions where the stage finished and finishStage removed the work orders before a retry path tried to start it again.","solutions":["Ensure createWorkOrders(...) is called for the stage number before startStage(stageId)","Check the controller's state-machine ordering (startWorkForStage) to confirm the stage is transitioning from a phase where work orders exist","If this follows a controller restart, re-run the query or verify the kernel snapshot persisted in the task includes work orders","Guard with a kernel API check (e.g. isStageKnown / getStagePhase) before calling startStage"],"exampleFix":"// before\nkernel.startStage(stageId);\n\n// after\nif (kernel.getStagePhase(stageId) == ControllerStagePhase.NEW) {\n  kernel.startStage(stageId);\n}","handlingStrategy":"validation","validationCode":"if (queryKernel.getStagePhase(stageId) == ControllerStagePhase.NEW) {\n  queryKernel.startStage(stageId);\n}","typeGuard":"boolean canStartStage(StageId stageId) {\n  try {\n    return queryKernel.getStagePhase(stageId) == ControllerStagePhase.NEW;\n  } catch (IllegalArgumentException e) {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  queryKernel.startStage(stageId);\n} catch (IllegalStateException e) {\n  LOG.warn(e, \"Stage %s has no work orders; skipping start\", stageId);\n}","preventionTips":["Always call createWorkOrders for the stage before startStage","Only drive stage transitions through the controller state machine, never ad hoc","After controller restart, reload the kernel snapshot before resuming transitions","Treat startStage as one-shot and track which stages have already been started"],"tags":["msq","state-machine","controller"],"backgroundTag":"internal-invariant-violation","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"}