apache/druid · error · IllegalStateException

Status report not available

Error message

Status report not available

What it means

getStatusReport() on TaskReportQueryListener throws this ISE when statusReport is still null — i.e. the controller is asked for a status report before the listener has ever received one. It is a lifecycle/state guard: the report is only populated once all stages finish and buildStatusReport is called, so an early getStatusReport call indicates the query has not produced status output yet.

Solutions

  1. Wait for the task to progress and poll the report again; status is published when stages complete.
  2. Check the controller task logs for an earlier failure that prevented the status report from being built.
  3. If this occurs persistently, look for exceptions in report writing/serialization (IOException paths) that left statusReport unset.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/indexing/TaskReportQueryListener.java:255 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/indexing/TaskReportQueryListener.java:255

      if (report.getCounters() != null) {
        writeObjectField(FIELD_COUNTERS, report.getCounters());
      }

      jg.writeEndObject(); // End MSQTaskReportPayload
      jg.writeEndObject(); // End MSQTaskReport
      jg.writeObjectField(TaskContextReport.REPORT_KEY, new TaskContextReport(taskId, taskContext));
      jg.writeEndObject(); // End report
      jg.close();
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public MSQStatusReport getStatusReport()
  {
    if (statusReport == null) {
      throw new ISE("Status report not available");
    }

    return statusReport;
  }

  /**
   * Initialize {@link #jg}, if it wasn't already set up. Writes the object start marker, too.
   */
  private void openGenerator() throws IOException
  {
    if (jg == null) {
      jg = jsonMapper.createGenerator(reportSink.get());
      jg.writeStartObject(); // Start report
      jg.writeObjectFieldStart(MSQTaskReport.REPORT_KEY); // Start MSQTaskReport
      jg.writeStringField(FIELD_TYPE, MSQTaskReport.REPORT_KEY);
      jg.writeStringField(FIELD_TASK_ID, taskId);
      jg.writeObjectFieldStart(FIELD_PAYLOAD); // Start MSQTaskReportPayload
    }

View on GitHub (pinned to 9b90983fd2)