{"record":{"id":"c00a7d93c752ca6a","repo":"prestodb/presto","slug":"mismatched-column-aliases","errorCode":"MISMATCHED_COLUMN_ALIASES","errorMessage":"Column alias list has %s entries but subquery has %s columns","messagePattern":"Column alias list has (.+?) entries but subquery has (.+?) columns","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java","lineNumber":1628,"sourceCode":"            Set<String> names = new HashSet<>();\n            for (Field field : descriptor.getVisibleFields()) {\n                Optional<String> fieldName = field.getName();\n                if (!fieldName.isPresent()) {\n                    throw new SemanticException(COLUMN_NAME_NOT_SPECIFIED, node, \"Column name not specified at position %s\", descriptor.indexOf(field) + 1);\n                }\n                if (!names.add(fieldName.get())) {\n                    throw new SemanticException(DUPLICATE_COLUMN_NAME, node, \"Column name '%s' specified more than once\", fieldName.get());\n                }\n                if (field.getType().equals(UNKNOWN)) {\n                    throw new SemanticException(COLUMN_TYPE_UNKNOWN, node, \"Column type is unknown: %s\", fieldName.get());\n                }\n            }\n        }\n\n        private void validateColumnAliases(List<Identifier> columnAliases, int sourceColumnSize)\n        {\n            if (columnAliases.size() != sourceColumnSize) {\n                throw new SemanticException(\n                        MISMATCHED_COLUMN_ALIASES,\n                        columnAliases.get(0),\n                        \"Column alias list has %s entries but subquery has %s columns\",\n                        columnAliases.size(),\n                        sourceColumnSize);\n            }\n            Set<String> names = new HashSet<>();\n            for (Identifier identifier : columnAliases) {\n                if (names.contains(identifier.getValueLowerCase())) {\n                    throw new SemanticException(DUPLICATE_COLUMN_NAME, identifier, \"Column name '%s' specified more than once\", identifier.getValue());\n                }\n                names.add(identifier.getValueLowerCase());\n            }\n        }\n\n        private void validateBaseTables(List<Table> baseTables, Node node)\n        {\n            for (Table baseTable : baseTables) {","sourceCodeStart":1610,"sourceCodeEnd":1646,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java#L1610-L1646","documentation":"Presto throws this SemanticException when an ALIAS clause (e.g. in a table or UNNEST relation) supplies a different number of column aliases than the subquery/underlying relation produces columns. The analyzer validates the alias list against the actual column count during query analysis before execution. This is a static SQL-semantic error, not a runtime data error.","triggerScenarios":"Writing `SELECT * FROM (SELECT 1, 2, 3) t(a, b)` or a table-valued/relation reference with a column alias list whose length (2) does not equal the subquery's column count (3). validateColumnAliases compares columnAliases.size() to sourceColumnSize and throws on inequality.","commonSituations":"Hand-edited queries where a subquery was later changed to add/remove columns but the alias list was not updated; ORM or query-builder generated aliases drifting from the projection; copy-pasting an alias list from a similar but wider table definition.","solutions":["Count the columns produced by the subquery and make the alias list exactly the same length.","Remove the alias list entirely (e.g. `t` instead of `t(a, b, c)`) if named columns are not required.","Update the alias list automatically whenever the subquery projection changes; add a query-formatting/lint check in CI.","If caught programmatically, catch com.facebook.presto.sql.analyzer.SemanticException and check getErrorCode() == MISMATCHED_COLUMN_ALIASES to surface a clear message to the end user."],"exampleFix":"// before\nSELECT * FROM (SELECT id, name, created_at FROM users) u(id, name)\n// after\nSELECT * FROM (SELECT id, name, created_at FROM users) u(id, name, created_at)","handlingStrategy":"validation","validationCode":"int projected = countProjectionColumns(subquerySql); // via metadata or a lightweight parser\nif (aliasList != null && aliasList.size() != projected) {\n    throw new IllegalArgumentException(\"alias list has \" + aliasList.size() + \" entries but subquery has \" + projected + \" columns\");\n}","typeGuard":null,"tryCatchPattern":"try { runQuery(sql); } catch (SemanticException e) { if (\"MISMATCHED_COLUMN_ALIASES\".equals(e.getCode().getName())) { fixAliasListAndRetry(sql); } else { throw e; } }","preventionTips":["Keep the alias list adjacent to the subquery and update both in the same edit.","Omit column aliases when the subquery projection changes frequently.","Add SQL linting to CI that verifies alias-list arity against projections."],"tags":["sql","query-analysis","column-aliases","semantic-error"],"backgroundTag":"column-alias-count-mismatch","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"}