apache/druid · error · IllegalStateException

Expected [%s], but [%s] is in use

Error message

Expected [%s], but [%s] is in use

What it means

Thrown by an HTTP endpoint on ParallelIndexSupervisorTask (e.g. the /subtaskspecs or related REST API) when the currently active runner is not a SinglePhaseParallelIndexTaskRunner. Those endpoints only make sense for single-phase parallel ingestion; calling them on a task running a different runner is an invalid request.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexSupervisorTask.java:1404

   */
  @POST
  @Path("/segment/allocate")
  @Produces(SmileMediaTypes.APPLICATION_JACKSON_SMILE)
  @Consumes(SmileMediaTypes.APPLICATION_JACKSON_SMILE)
  public Response allocateSegment(
      Object param,
      @Context final HttpServletRequest req
  )
  {
    ChatHandlers.authorizationCheck(req, Action.READ, getDataSource(), authorizerMapper);

    if (toolbox == null) {
      return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("task is not running yet").build();
    }

    ParallelIndexTaskRunner runner = Preconditions.checkNotNull(getCurrentRunner(), "runner");
    if (!(runner instanceof SinglePhaseParallelIndexTaskRunner)) {
      throw new ISE(
          "Expected [%s], but [%s] is in use",
          SinglePhaseParallelIndexTaskRunner.class.getName(),
          runner.getClass().getName()
      );
    }

    // This context is set in the constructor of ParallelIndexSupervisorTask if it's not set by others.
    final boolean useLineageBasedSegmentAllocation = Preconditions.checkNotNull(
        getContextValue(SinglePhaseParallelIndexTaskRunner.CTX_USE_LINEAGE_BASED_SEGMENT_ALLOCATION_KEY),
        "useLineageBasedSegmentAllocation in taskContext"
    );

    try {
      final SegmentIdWithShardSpec segmentIdentifier;
      if (useLineageBasedSegmentAllocation) {
        SegmentAllocationRequest request = toolbox.getJsonMapper().convertValue(param, SegmentAllocationRequest.class);
        segmentIdentifier = ((SinglePhaseParallelIndexTaskRunner) runner)
            .allocateNewSegment(

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Only call subtask-spec endpoints on tasks using SinglePhaseParallelIndexTaskRunner; check the task type first.
  2. For multi-phase tasks use the appropriate endpoints (/subtaskspecs vs phase-specific APIs) or the overlord task report.
  3. Update monitoring scripts to branch on task 'type' (index_parallel vs index/replace).

Example fix

// before
curl $OVERLORD/druid/indexer/v1/task/$taskId/subtaskspecs
// after: only for index_parallel tasks
type=$(curl $OVERLORD/druid/indexer/v1/task/$taskId | jq -r .payload.type)
if [ "$type" = "index_parallel" ]; then
  curl $OVERLORD/druid/indexer/v1/task/$taskId/subtaskspecs
fi
Defensive patterns

Strategy: type-guard

Type guard

function canQuerySubtaskSpecs(taskType) {
  return taskType === 'index_parallel';
}

Prevention

When it happens

Trigger: Hitting task REST endpoints like /druid/indexer/v1/task/{id}/subtaskspecs or /unparseableEvents (subtask spec APIs) against a task whose runner is a two-phase/sequential runner (e.g. runTask via SQL-generated replace tasks).

Common situations: Scripts or UI integrations that query subtask APIs for every batch task regardless of its type; monitoring tools pointing at compaction or MSQ replace tasks that use other runners.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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