prestodb/presto · error · SemanticException

DUPLICATE_COLUMN_NAME

DUPLICATE_COLUMN_NAME

Error message

Insert column name is specified more than once: %s

What it means

When an INSERT statement lists its target columns explicitly, Presto requires each column to appear at most once. StatementAnalyzer.visitInsert uses a HashSet while iterating the provided insertColumns; if a name is added twice (columnNames.add returns false), it throws DUPLICATE_COLUMN_NAME.

Source

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

            List<String> tableColumns = columnsMetadata.stream()
                    .filter(column -> !column.isHidden())
                    .map(ColumnMetadata::getName)
                    .collect(toImmutableList());

            List<String> insertColumns;
            if (insert.getColumns().isPresent()) {
                insertColumns = insert.getColumns().get().stream()
                        .map(Identifier::getValue)
                        .map(column -> metadata.normalizeIdentifier(session, targetTable.getCatalogName(), column))
                        .collect(toImmutableList());

                Set<String> columnNames = new HashSet<>();
                for (String insertColumn : insertColumns) {
                    if (!tableColumns.contains(insertColumn)) {
                        throw new SemanticException(MISSING_COLUMN, insert, "Insert column name does not exist in target table: %s", insertColumn);
                    }
                    if (!columnNames.add(insertColumn)) {
                        throw new SemanticException(DUPLICATE_COLUMN_NAME, insert, "Insert column name is specified more than once: %s", insertColumn);
                    }
                }
            }
            else {
                insertColumns = tableColumns;
            }

            List<ColumnMetadata> expectedColumns = insertColumns.stream()
                    .map(insertColumn -> getColumnMetadata(columnsMetadata, insertColumn))
                    .collect(toImmutableList());

            checkTypesMatchForInsert(insert, queryScope, expectedColumns);

            Map<String, ColumnHandle> columnHandles = tableColumnsMetadata.getColumnHandles();
            analysis.setInsert(new Analysis.Insert(
                    tableColumnsMetadata.getTableHandle().get(),
                    insertColumns.stream().map(columnHandles::get).collect(toImmutableList())));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Remove the duplicated name from the INSERT column list so each target column appears exactly once.
  2. If your driver/templating builds the column list, deduplicate or assert uniqueness on the list before rendering the SQL.
  3. Omit the column list entirely to target all table columns in order (values must then match the full table schema).

Example fix

// before
INSERT INTO orders (orderkey, custkey, custkey) VALUES (1, 2, 2);
// after
INSERT INTO orders (orderkey, custkey) VALUES (1, 2);
Defensive patterns

Strategy: validation

Validate before calling

// JS-style pre-check on generated column lists:
const cols = ['orderkey', 'custkey', 'custkey'];
const dupes = cols.filter((c, i) => cols.indexOf(c) !== i);
if (dupes.length) throw new Error('Duplicate INSERT columns: ' + dupes.join(', '));

Prevention

When it happens

Trigger: INSERT INTO t (a, a, b) VALUES (...) — the same column name appears twice in the explicit column list of the INSERT.

Common situations: Copy-paste or generated SQL accidentally repeating a column; adding a column to the list without removing the old positional entry; templating bugs in query builders that concatenate column lists.

Related errors


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