prestodb/presto · error · PinotException
PINOT_INVALID_SQL_GENERATED
PINOT_INVALID_SQL_GENERATED
Error message
Expected column handle %s to be present in the handles %s corresponding to the segment Pinot SQL
What it means
When filling a page, each column handle needed by the scan is looked up by index in the split's expected column handles (the columns the generated Pinot SQL returns). If a requested handle is absent, the generated SQL and the scan disagree, indicating a connector bug, so it throws PINOT_INVALID_SQL_GENERATED.
Source
Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/PinotSegmentPageSource.java:166
// This is the list of handles we came up with when generating the SQL
// This could be a superset/permutation of the handles being requested in this scan
List<PinotColumnHandle> expectedColumnHandles = split.getExpectedColumnHandles();
PageBuilder pageBuilder = new PageBuilder(columnTypes);
// Note that declared positions in the Page should be the same with number of rows in each Block
pageBuilder.declarePositions(currentDataTable.getDataTable().getNumberOfRows());
for (int columnHandleIndex = 0; columnHandleIndex < columnHandles.size(); columnHandleIndex++) {
BlockBuilder blockBuilder = pageBuilder.getBlockBuilder(columnHandleIndex);
Type columnType = columnTypes.get(columnHandleIndex);
// Write a block for each column in the original order.
PinotColumnHandle handle = columnHandles.get(columnHandleIndex);
// map the handle needed by the scan to its index corresponding to the generated SQL
// All handles requested by the scan should be a subset of the expected handles
// ie., the expected column handles (corresponding to the generated SQL) can contain
// extra columns that we drop.
int indexReturnedByPinot = expectedColumnHandles.indexOf(handle);
if (indexReturnedByPinot < 0) {
throw new PinotException(
PINOT_INVALID_SQL_GENERATED,
split.getSegmentPinotQuery(),
String.format("Expected column handle %s to be present in the handles %s corresponding to the segment Pinot SQL", handle, expectedColumnHandles));
}
writeBlock(blockBuilder, columnType, indexReturnedByPinot);
}
return pageBuilder.build();
}
/**
* @return constructed page for pinot data.
*/
@Override
public Page getNextPage()
{
if (closed) {
return null;View on GitHub (pinned to 55bb57d202)
Solutions
- Retry after clearing Presto metadata/plan caches and resubmitting the query
- Capture the full query and generated Pinot SQL (split.getSegmentPinotQuery()) and file a connector bug with the plan
- Ensure all nodes run identical connector versions; restart the cluster after upgrades
- Simplify or reshape the query (fewer projected columns, simpler predicates) as a workaround
Defensive patterns
Strategy: fallback
Try / catch
catch (PinotException e) {
if (e.getErrorCode() == PINOT_INVALID_SQL_GENERATED.toErrorCode().getCode()) {
// clear caches, restart/upgrade connector, and file a bug with the plan + generated SQL
}
} Prevention
- Run identical connector versions on all nodes
- Reproduce with a minimal query and report the generated Pinot SQL upstream
- Avoid unsupported query shapes known to confuse SQL generation; keep projections simple
When it happens
Trigger: fillNextPage calls expectedColumnHandles.indexOf(handle) and gets -1 for a scan's column handle — the SQL generator omitted a column that the scan expects.
Common situations: Connector bugs after schema changes or query shapes (e.g. predicates synthesizing columns not in the output); mixed plugin versions where split metadata was produced by a different build; stale cached plans.
Related errors
- FUNCTION_IMPLEMENTATION_ERROR
- NOT_SUPPORTED
- Can't handle type:
- GENERIC_INTERNAL_ERROR
- GENERIC_INTERNAL_ERROR
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/e8c6466e90193e80.
Report an issue: GitHub.