prestodb/presto · error · SemanticException

MISMATCHED_COLUMN_ALIASES

MISMATCHED_COLUMN_ALIASES

Error message

Column alias list has %s entries but subquery has %s columns

What it means

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.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:1628

            Set<String> names = new HashSet<>();
            for (Field field : descriptor.getVisibleFields()) {
                Optional<String> fieldName = field.getName();
                if (!fieldName.isPresent()) {
                    throw new SemanticException(COLUMN_NAME_NOT_SPECIFIED, node, "Column name not specified at position %s", descriptor.indexOf(field) + 1);
                }
                if (!names.add(fieldName.get())) {
                    throw new SemanticException(DUPLICATE_COLUMN_NAME, node, "Column name '%s' specified more than once", fieldName.get());
                }
                if (field.getType().equals(UNKNOWN)) {
                    throw new SemanticException(COLUMN_TYPE_UNKNOWN, node, "Column type is unknown: %s", fieldName.get());
                }
            }
        }

        private void validateColumnAliases(List<Identifier> columnAliases, int sourceColumnSize)
        {
            if (columnAliases.size() != sourceColumnSize) {
                throw new SemanticException(
                        MISMATCHED_COLUMN_ALIASES,
                        columnAliases.get(0),
                        "Column alias list has %s entries but subquery has %s columns",
                        columnAliases.size(),
                        sourceColumnSize);
            }
            Set<String> names = new HashSet<>();
            for (Identifier identifier : columnAliases) {
                if (names.contains(identifier.getValueLowerCase())) {
                    throw new SemanticException(DUPLICATE_COLUMN_NAME, identifier, "Column name '%s' specified more than once", identifier.getValue());
                }
                names.add(identifier.getValueLowerCase());
            }
        }

        private void validateBaseTables(List<Table> baseTables, Node node)
        {
            for (Table baseTable : baseTables) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Count the columns produced by the subquery and make the alias list exactly the same length.
  2. Remove the alias list entirely (e.g. `t` instead of `t(a, b, c)`) if named columns are not required.
  3. Update the alias list automatically whenever the subquery projection changes; add a query-formatting/lint check in CI.
  4. 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.

Example fix

// before
SELECT * FROM (SELECT id, name, created_at FROM users) u(id, name)
// after
SELECT * FROM (SELECT id, name, created_at FROM users) u(id, name, created_at)
Defensive patterns

Strategy: validation

Validate before calling

int projected = countProjectionColumns(subquerySql); // via metadata or a lightweight parser
if (aliasList != null && aliasList.size() != projected) {
    throw new IllegalArgumentException("alias list has " + aliasList.size() + " entries but subquery has " + projected + " columns");
}

Try / catch

try { runQuery(sql); } catch (SemanticException e) { if ("MISMATCHED_COLUMN_ALIASES".equals(e.getCode().getName())) { fixAliasListAndRetry(sql); } else { throw e; } }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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