{"record":{"id":"db580e79eecaf862","repo":"prestodb/presto","slug":"pinot-unsupported-expression-db580e","errorCode":"PINOT_UNSUPPORTED_EXPRESSION","errorMessage":"Expected Pinot column handle %s to occur only once, but we have: %s","messagePattern":"Expected Pinot column handle (.+?) to occur only once, but we have: (.+?)","errorType":"error_code","errorClass":"PinotException","httpStatus":null,"severity":"error","filePath":"presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotQueryGeneratorContext.java","lineNumber":441,"sourceCode":"                        outputColumn,\n                        Joiner.on(\",\").withKeyValueSeparator(\":\").join(selections)));\n            }\n            expressionsInPinotOrder.put(outputColumn, outputColumnDefinition);\n        }\n\n        checkSupported(\n                assignments.size() <= expressionsInPinotOrder.keySet().stream().filter(key -> !hiddenColumnSet.contains(key)).count(),\n                \"Expected returned expressions %s is a superset of selections %s\",\n                Joiner.on(\",\").withKeyValueSeparator(\":\").join(expressionsInPinotOrder),\n                Joiner.on(\",\").withKeyValueSeparator(\"=\").join(assignments));\n\n        Map<VariableReferenceExpression, Integer> assignmentToIndex = new HashMap<>();\n        Iterator<Map.Entry<VariableReferenceExpression, PinotColumnHandle>> assignmentsIterator = assignments.entrySet().iterator();\n        for (int i = 0; i < assignments.size(); i++) {\n            VariableReferenceExpression key = assignmentsIterator.next().getKey();\n            Integer previous = assignmentToIndex.put(key, i);\n            if (previous != null) {\n                throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.of(query), format(\"Expected Pinot column handle %s to occur only once, but we have: %s\", key, Joiner.on(\",\").withKeyValueSeparator(\"=\").join(assignments)));\n            }\n        }\n\n        ImmutableList.Builder<Integer> outputIndices = ImmutableList.builder();\n        for (Map.Entry<VariableReferenceExpression, Selection> expression : expressionsInPinotOrder.entrySet()) {\n            Integer index;\n            if (hiddenColumnSet.contains(expression.getKey())) {\n                index = -1; // negative output index means to skip this value returned by pinot at query time\n            }\n            else {\n                index = assignmentToIndex.getOrDefault(expression.getKey(), -1); // negative output index means to skip this value returned by pinot at query time\n            }\n            outputIndices.add(index);\n        }\n        return outputIndices.build();\n    }\n\n    public LinkedHashMap<VariableReferenceExpression, PinotColumnHandle> getAssignments()","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotQueryGeneratorContext.java#L423-L459","documentation":"When building the assignments-to-index map, the generator expects each PinotColumnHandle variable in the assignments map to appear exactly once. A duplicate key means the same column handle is assigned to multiple output positions, which Pinot's columnar output cannot disambiguate; the generator throws PINOT_UNSUPPORTED_EXPRESSION with the full assignment list.","triggerScenarios":"A plan where the same Pinot column handle is assigned to two different VariableReferenceExpressions (duplicate assignments), e.g. the same column selected twice through different variable names or duplicated by a join/union rewrite before pushdown.","commonSituations":"Queries selecting the same column multiple times with different aliases combined with pushdown; planner rewrites (dedup/pruning) producing shared handles; connector version changes in assignment keying.","solutions":["Remove duplicate column references in the SELECT list (select the column once and reuse it).","Rewrite the query so each referenced column appears under a single variable/alias in the pushed plan.","If a single-reference query triggers it, the assignment construction has a bug — report with the query and assignments from the message."],"exampleFix":"// before\nSELECT user_id, user_id AS uid FROM events; // duplicate column handle\n// after\nSELECT user_id FROM events;","handlingStrategy":"validation","validationCode":"// Deduplicate column references in the SELECT list before running\nList<String> deduped = selectTerms.stream().distinct().collect(Collectors.toList());\nif (deduped.size() != selectTerms.size()) {\n    selectTerms = deduped; // or alias via Presto-side projection instead\n}","typeGuard":null,"tryCatchPattern":"try {\n    runQuery(sql);\n} catch (PinotException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"to occur only once\")) {\n        runQuery(deduplicatedSql);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Select each column at most once in Pinot-pushed queries; alias client-side.","Avoid cross-join/union rewrites that share one column handle for multiple outputs.","Review planner rewrites that duplicate assignments before pushdown."],"tags":["pinot","pushdown","duplicate-column","unsupported-expression"],"backgroundTag":"duplicate-column-assignment","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}