apache/druid · error · RE

Expected a single column but got

Error message

Expected a single column but got [%s] columns. Please check broker logs for more information.

What it means

After confirming exactly one row, buildTaskResponse requires that row to have exactly one column containing the taskId. If the row is null or has a different column count, this RE is thrown. It protects the /sql/statements response contract: the task-status query must return a single taskId value.

Solutions

  1. Inspect broker logs for the internal task-status query and compare its select list to the expected single-column taskId projection.
  2. Ensure all cluster nodes run the same Druid version (no mixed-version schema mismatch).
  3. Remove any custom extensions/filters that could alter the status query, then retry the statements API call.
  4. If persistent, file/check Druid issue tracker for regressions in SqlStatementResource.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the status query response shape client-side before consuming
Object[] row = rows.get(0);
if (row == null || row.length != 1) {
  throw new IllegalStateException("Unexpected task-status row shape, expected single taskId column");
}

Try / catch

try {
  submitAsync(query);
} catch (DruidException e) {
  if (e.getMessage().contains("Expected a single column")) {
    upgradeOrAlignClusterVersions(); // schema mismatch between nodes
  }
  throw e;
}

Prevention

When it happens

Trigger: The single row returned by the internal task-status query has zero or multiple columns — e.g. a changed/incorrect internal SELECT for the ingestion task id, or an unexpected engine result schema after an upgrade or a custom query modification.

Common situations: Running a modified/patched Druid where the internal status query's projection changed; interacting with the statements API through a proxy that rewrites the request; mixed-version cluster where broker and MSQ engine disagree on the status row schema.

Related errors


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

Appendix: source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/sql/resources/SqlStatementResource.java:530

      return responseBuilder.build();
    }
    catch (Throwable e) {
      // make sure to close yielder if anything happened before starting to serialize the response.
      yielder0.close();
      throw e;
    }
  }

  private Response buildTaskResponse(Sequence<Object[]> sequence, AuthenticationResult authenticationResult)
  {
    List<Object[]> rows = sequence.toList();
    int numRows = rows.size();
    if (numRows != 1) {
      throw new RE("Expected a single row but got [%d] rows. Please check broker logs for more information.", numRows);
    }
    Object[] firstRow = rows.get(0);
    if (firstRow == null || firstRow.length != 1) {
      throw new RE(
          "Expected a single column but got [%s] columns. Please check broker logs for more information.",
          firstRow == null ? 0 : firstRow.length
      );
    }
    String taskId = String.valueOf(firstRow[0]);

    Optional<SqlStatementResult> statementResult = getStatementStatus(
        taskId,
        authenticationResult,
        true,
        Action.READ,
        false
    );

    if (statementResult.isPresent()) {
      return Response.status(Response.Status.OK).entity(statementResult.get()).build();
    } else {
      return buildNonOkResponse(

View on GitHub (pinned to 9b90983fd2)