prestodb/presto · error · PrestoException

DRUID_BROKER_RESULT_ERROR

DRUID_BROKER_RESULT_ERROR

Error message

${rootNode.findValue("errorMessage").asText()}

What it means

This PrestoException (DRUID_BROKER_RESULT_ERROR) is thrown by DruidBrokerPageSource.getNextPage when a line of the Druid broker's newline-delimited JSON response contains an "errorMessage" field. Druid's /druid/v2/sql endpoint returns per-row error objects (e.g. {"queryNumber":..., "errorMessage":"..."}) when the SQL query fails server-side, and the connector surfaces that message directly to the user instead of returning bad data. The check is skipped if the query itself selected a column literally named "errorMessage".

Source

Thrown at presto-druid/src/main/java/com/facebook/presto/druid/DruidBrokerPageSource.java:127

        if (finished) {
            return null;
        }

        long start = System.nanoTime();
        boolean columnHandlesHasErrorMessageField = columnHandles.stream().anyMatch(
                handle -> ((DruidColumnHandle) handle).getColumnName().equals("errorMessage"));
        try {
            String readLine;
            while ((readLine = responseStream.readLine()) != null) {
                // if read a blank line,it means read finish
                if (readLine.isEmpty()) {
                    finished = true;
                    break;
                }
                else {
                    JsonNode rootNode = OBJECT_MAPPER.readTree(readLine);
                    if (rootNode.has("errorMessage") && !columnHandlesHasErrorMessageField) {
                        throw new PrestoException(DRUID_BROKER_RESULT_ERROR, rootNode.findValue("errorMessage").asText());
                    }
                    for (int i = 0; i < columnHandles.size(); i++) {
                        Type type = columnTypes.get(i);
                        BlockBuilder blockBuilder = pageBuilder.getBlockBuilder(i);
                        JsonNode value = rootNode.get(((DruidColumnHandle) columnHandles.get(i)).getColumnName());
                        if (value == null || value.isNull()) {
                            blockBuilder.appendNull();
                            continue;
                        }
                        if (type instanceof BigintType) {
                            type.writeLong(blockBuilder, value.longValue());
                        }
                        else if (type instanceof DoubleType) {
                            type.writeDouble(blockBuilder, value.doubleValue());
                        }
                        else if (type instanceof RealType) {
                            type.writeLong(blockBuilder, floatToRawIntBits(value.floatValue()));
                        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Read the embedded errorMessage in the exception text — it is Druid's own reason (e.g. unknown column, timeout) and fix the query accordingly.
  2. Validate the SQL/datasource by running the query directly against the Druid broker (e.g. curl POST to /druid/v2/sql) to confirm the failure is server-side.
  3. Check Druid broker logs and query timeout/resource-limit configs (maxScatterGatherBytes, druid.query.timeouts), and raise them if the query is being killed.
  4. If your table intentionally has a column named errorMessage, note the connector will not treat it as a failure signal; otherwise rename or avoid shadowing the reserved field.
  5. Refresh Presto's metadata cache (SYSTEM.drop_metadata_cache or restart) if the datasource was recently dropped/recreated.

Example fix

// before: query fails server-side with unclear failure
SELECT unknown_col FROM druid.mytable

// after: verify the column exists first, or use INFORMATION_SCHEMA
SELECT COLUMN_NAME FROM druid.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'mytable';
-- then query only existing columns, e.g.
SELECT real_col FROM druid.mytable
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the datasource/columns before querying:
// SELECT COLUMN_NAME FROM druid.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'mytable';
// Ensure every referenced column exists and no query fails server-side.
curl -s -XPOST 'http://druid-broker:8082/druid/v2/sql' \
  -H 'Content-Type: application/json' \
  -d '{"query":"SELECT 1 FROM mytable LIMIT 1"}'

Try / catch

try {
    connector.execute(query);
} catch (PrestoException e) {
    if (DRUID_BROKER_RESULT_ERROR.toErrorCode().equals(e.getErrorCode())) {
        // e.getMessage() is Druid's errorMessage payload — inspect query validity/limits
        log.error("Druid query failed server-side: " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Streaming OBJECT_LINES results from DruidBrokerPageSource.getNextPage when any parsed JSON line has a non-null "errorMessage" field and no selected column is named "errorMessage" — i.e. the Druid broker rejected or failed the SQL query mid-stream.

Common situations: Invalid DQL/SQL sent to Druid (unknown column, bad function, syntax error); Druid query timeout or resource limits (maxScatterGatherBytes, query quotas); broker unable to reach historical nodes; Druid version/config changes altering the SQL API; the table or datasource being queried does not exist or segments are unavailable.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/69ea34c97282f282. Report an issue: GitHub.