apache/druid · error · RE
Expected a single row but got
Error message
Expected a single row but got [%d] rows. Please check broker logs for more information.
What it means
SqlStatementResource.buildTaskResponse materializes the task-status query sequence and requires exactly one row (the row carrying the taskId). If numRows != 1 this RE is thrown. The /sql/statements endpoint expects the underlying task status query to return a single row; any other cardinality means the engine returned an unexpected result shape.
Solutions
- Check broker and overlord logs for the actual task status query outcome and the MSQ task's fate.
- Look up the controller task id in the overlord console to see if it failed at startup; fix the underlying query error and resubmit.
- Retry the request if it was a transient desync between broker and overlord.
- Verify Druid service versions are consistent so the task-status query contract is respected.
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// before using the statements API, confirm the task exists // GET /druid/indexer/v1/task/<controllerTaskId>/status returns 200 and non-null status
Try / catch
try {
submitAsync(query);
} catch (DruidException e) {
if (e.getMessage().contains("Expected a single row")) {
checkOverlordForTaskFailure(); // task died before status row was produced
resubmitQuery();
} else { throw e; }
} Prevention
- Check overlord task logs immediately when async submission returns odd row counts.
- Verify the controller task started successfully before polling results.
- Keep broker/overlord versions aligned.
When it happens
Trigger: POSTing to /druid/v2/sql/statements where the internally issued task-status query (SELECT of the ingestion task's state) yields zero rows (task not found/failed to start) or multiple rows, before extracting the taskId column.
Common situations: Querying the async statements API when the MSQ controller task died instantly and its status row is missing; broker/controller desync so the status lookup returns multiple entries; client bugs submitting duplicate/odd queries.
Related errors
- Expected a single column but got
- Failed to handle query
- Query [ ] was not found. The query details are no longer…
- The current user[ ] cannot view query id[ ] since the query…
- Unable to stream results back for query
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/4e92954cd1b621c9.
Report an issue: GitHub.
Appendix: source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/sql/resources/SqlStatementResource.java:526
if (sqlQuery.includeHeader()) {
responseBuilder.header(SqlResource.SQL_HEADER_RESPONSE_HEADER, SqlResource.SQL_HEADER_VALUE);
}
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
);
View on GitHub (pinned to 9b90983fd2)