prestodb/presto · error · PinotException
PINOT_EXCEPTION
PINOT_EXCEPTION
Error message
Expected pinot to contain %d columns but got %d: %s
What it means
The connector validates that the DataTable returned by Pinot has exactly as many columns as the column handles the split's generated SQL expected. A mismatch means the server returned a schema different from what the generated segment query asked for, so the connector throws PINOT_EXCEPTION with both counts and the actual schema.
Source
Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/PinotSegmentPageSource.java:112
this.columnTypes = columnHandles.stream()
.map(PinotSegmentPageSource::getTypeForBlock)
.collect(Collectors.toList());
this.pinotStreamingQueryClient = requireNonNull(pinotStreamingQueryClient, "pinotStreamingQueryClient is null");
}
public static void checkExceptions(DataTable dataTable, PinotSplit split, boolean markDataFetchExceptionsAsRetriable)
{
List<String> exceptions = dataTable.getExceptions().values().stream().toList();
if (!exceptions.isEmpty()) {
throw new PinotException(
markDataFetchExceptionsAsRetriable ? PINOT_DATA_FETCH_EXCEPTION : PINOT_EXCEPTION,
split.getSegmentPinotQuery(),
String.format("Encountered %d pinot exceptions for split %s: %s", exceptions.size(), split, exceptions));
}
int numColumnsExpected = split.getExpectedColumnHandles().size();
int numColumnsActual = dataTable.getDataSchema().size();
if (numColumnsActual != numColumnsExpected) {
throw new PinotException(
PINOT_EXCEPTION,
split.getSegmentPinotQuery(),
String.format("Expected pinot to contain %d columns but got %d: %s", numColumnsExpected, numColumnsActual, dataTable.getDataSchema()));
}
}
@Override
public long getCompletedBytes()
{
return completedBytes;
}
@Override
public long getReadTimeNanos()
{
return readTimeNanos;
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Compare the actual DataSchema in the message against expected handles to spot the missing/extra column
- Sync the Pinot table schema: reload segments or refresh metadata so all segments match the Presto connector's view
- Check for Pinot broker/server version mismatches and align cluster versions
- Re-run DESCRIBE / refresh Presto metadata cache for the table, then retry
Defensive patterns
Strategy: validation
Validate before calling
// refresh metadata and verify schema consistency before querying // DESCRIBE table; ensure columns exist in Pinot and all segments are refreshed
Try / catch
catch (PinotException e) {
if (String.valueOf(e.getMessage()).startsWith("Expected pinot to contain")) {
// compare expected vs actual schema in message; resync Pinot schema/metadata
}
} Prevention
- Keep Presto connector and Pinot cluster versions aligned
- Refresh Pinot segments after schema evolution so all segments share the schema
- Clear Presto metadata caches after Pinot schema changes
When it happens
Trigger: checkExceptions compares split.getExpectedColumnHandles().size() with dataTable.getDataSchema().size() and they differ — e.g. Pinot dropped, added, or renamed output columns relative to the generated SQL.
Common situations: Pinot version skew changing result schema behavior; queries hitting dynamic/schema-evolution mismatches where a column exists in Presto's metadata but not in all segments; broker rewriting the query.
Related errors
- PINOT_DATA_FETCH_EXCEPTION_OR_PINOT_EXCEPTION
- PINOT_DATA_FETCH_EXCEPTION
- currentFieldIndexToWrite is not valid
- Request has different number of fields than column handles:
- HIVE_INVALID_ENCRYPTION_METADATA
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/c4e9c2da1b6e374a.
Report an issue: GitHub.