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

  1. Retry after clearing Presto metadata/plan caches and resubmitting the query
  2. Capture the full query and generated Pinot SQL (split.getSegmentPinotQuery()) and file a connector bug with the plan
  3. Ensure all nodes run identical connector versions; restart the cluster after upgrades
  4. 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

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


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