prestodb/presto · error · PinotException
PINOT_UNEXPECTED_RESPONSE
PINOT_UNEXPECTED_RESPONSE
Error message
Empty routingTableEntries for %s. RoutingTable: %s
What it means
Thrown by getRoutingTableV1 when the controller's routing table response parses successfully but contains no routingTableEntries, i.e. Pinot cannot say which servers host the table's segments. The connector treats this as an unexpected controller response (PINOT_UNEXPECTED_RESPONSE).
Source
Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/PinotClusterInfoFetcher.java:438
catch (Exception e) {
return getRoutingTableV1(tableName, responseBody);
}
}
private Map<String, Map<String, List<String>>> getRoutingTableV1(String tableName, String responseBody)
{
ImmutableMap.Builder<String, Map<String, List<String>>> routingTableMap = ImmutableMap.builder();
routingTablesJsonCodec.fromJson(responseBody).getRoutingTableSnapshot().forEach(snapshot -> {
String tableNameWithType = snapshot.getTableName();
// Response could contain info for tableName that matches the original table by prefix.
// e.g. when table name is "table1", response could contain routingTable for "table1_staging"
if (!tableName.equals(extractRawTableName(tableNameWithType))) {
log.debug("Ignoring routingTable for %s", tableNameWithType);
}
else {
List<Map<String, List<String>>> routingTableEntriesList = snapshot.getRoutingTableEntries();
if (routingTableEntriesList.isEmpty()) {
throw new PinotException(
PINOT_UNEXPECTED_RESPONSE,
Optional.empty(),
String.format("Empty routingTableEntries for %s. RoutingTable: %s", tableName, responseBody));
}
// We are given multiple routing tables for a table, each with different segment to host assignments
// We pick one randomly, so that a retry may hit a different server
Map<String, List<String>> routingTableEntries = routingTableEntriesList.get(new Random().nextInt(routingTableEntriesList.size()));
ImmutableMap.Builder<String, List<String>> routingTableBuilder = ImmutableMap.builder();
routingTableEntries.forEach((host, segments) -> {
List<String> segmentsCopied = new ArrayList<>(segments);
Collections.shuffle(segmentsCopied);
routingTableBuilder.put(host, ImmutableList.copyOf(segmentsCopied));
});
routingTableMap.put(tableNameWithType, routingTableBuilder.build());
}
});
return routingTableMap.build();View on GitHub (pinned to 55bb57d202)
Solutions
- Check in Pinot whether the table has segments loaded (curl /tables/<table>/segments)
- If the table was just created, wait for the batch/stream ingestion to load segments
- Compare the Pinot controller version against the connector's expectations and inspect the logged responseBody
- Drop and recreate/reload the table's segments if routing state is permanently empty
Example fix
// before curl -X POST .../tables/myTable # created table, no segments // after curl -X POST .../segments/myTable/upload # load segments before querying
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the table has segments before routing curl -s http://<controller>:9000/tables/<table>/segments | jq '.segments | length'
Try / catch
try {
connector.listTables(...);
} catch (PinotException e) {
if (e.getMessage().contains("Empty routingTableEntries")) {
// treat table as not queryable; skip or alert
}
throw e;
} Prevention
- Never expose tables with zero loaded segments to Presto queries
- Wait for ingestion completeness checks before querying new tables
- Monitor Pinot routing state during segment rebalances
- Log and inspect the responseBody included in the error to debug controller responses
When it happens
Trigger: GET to the controller's routing table API returns a body whose snapshot has an empty routingTableEntries list for the requested table.
Common situations: Table exists but has no segments yet (just created, batch load not finished); table deleted while routing cache was being populated; Pinot controller returning degraded routing state during a rebalance; response body captured in the message shows the raw JSON.
Related errors
- PINOT_HTTP_ERROR
- PINOT_UNABLE_TO_FIND_INSTANCE
- PINOT_UNCLASSIFIED_ERROR
- PINOT_UNSUPPORTED_COLUMN_TYPE
- PINOT_UNEXPECTED_RESPONSE
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/8a2bcc7884b3f2d2.
Report an issue: GitHub.