prestodb/presto · critical · PrestoException

GENERIC_INTERNAL_ERROR

GENERIC_INTERNAL_ERROR

Error message

Duplicate column name: ${columnName}

What it means

While building a column-name-to-index map for a system table, createPageSource detects two ColumnMetadata entries with the same name and throws GENERIC_INTERNAL_ERROR. System tables are required to have unique column names; a duplicate indicates a broken connector/system-table definition, not a user error.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/connector/system/SystemPageSourceProvider.java:81

            ConnectorSplit split,
            List<ColumnHandle> columns,
            SplitContext splitContext)
    {
        requireNonNull(columns, "columns is null");
        SystemTransactionHandle systemTransaction = (SystemTransactionHandle) transactionHandle;
        SystemSplit systemSplit = (SystemSplit) split;
        SchemaTableName tableName = systemSplit.getTableHandle().getSchemaTableName();
        SystemTable systemTable = tables.getSystemTable(session, tableName)
                // table might disappear in the meantime
                .orElseThrow(() -> new PrestoException(NOT_FOUND, format("Table %s not found", tableName)));

        List<ColumnMetadata> tableColumns = systemTable.getTableMetadata().getColumns();

        Map<String, Integer> columnsByName = new HashMap<>();
        for (int i = 0; i < tableColumns.size(); i++) {
            ColumnMetadata column = tableColumns.get(i);
            if (columnsByName.put(column.getName(), i) != null) {
                throw new PrestoException(GENERIC_INTERNAL_ERROR, "Duplicate column name: " + column.getName());
            }
        }

        ImmutableList.Builder<Integer> userToSystemFieldIndex = ImmutableList.builder();
        for (ColumnHandle column : columns) {
            String columnName = ((SystemColumnHandle) column).getColumnName();

            Integer index = columnsByName.get(columnName);
            if (index == null) {
                throw new PrestoException(GENERIC_INTERNAL_ERROR, format("Column does not exist: %s.%s", tableName, columnName));
            }

            userToSystemFieldIndex.add(index);
        }

        TupleDomain<ColumnHandle> constraint = systemSplit.getConstraint();
        ImmutableMap.Builder<Integer, Domain> newConstraints = ImmutableMap.builder();
        for (Map.Entry<ColumnHandle, Domain> entry : constraint.getDomains().get().entrySet()) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Fix the connector's SystemTable metadata so every column name is unique and case-insensitively distinct.
  2. For dynamically generated columns, deduplicate names before building ColumnMetadata.
  3. If third-party, upgrade or report the connector; no client-side workaround exists for this internal invariant.

Example fix

// before
columns.add(new ColumnMetadata("snapshot", BIGINT));
columns.add(new ColumnMetadata("snapshot", VARCHAR)); // duplicate
// after
columns.add(new ColumnMetadata("snapshot_count", BIGINT));
columns.add(new ColumnMetadata("snapshot_name", VARCHAR));
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (ColumnMetadata c : systemTable.getTableMetadata().getColumns()) {
    if (!seen.add(c.getName().toLowerCase(Locale.ROOT))) {
        throw new IllegalStateException("Duplicate system table column: " + c.getName());
    }
}

Try / catch

try { readSystemTable(...); }
catch (PrestoException e) { if (e.getErrorCode() == StandardErrorCode.GENERIC_INTERNAL_ERROR.toErrorCode() && e.getMessage().startsWith("Duplicate column")) { reportConnectorBug(); } throw e; }

Prevention

When it happens

Trigger: Reading any system table whose getTableMetadata().getColumns() contains a repeated column name (e.g. connector declares columns 'snapshot' and 'snapshot' or duplicates via case-insensitive collision).

Common situations: Custom connectors hand-writing SystemTable metadata with copy-pasted column definitions; connectors generating columns dynamically (e.g. per-metric tables) where generated names collide; case-variant names ('Id' vs 'id') colliding in the lowercase map.

Related errors


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