apache/seatunnel · error · ParserException

Insert sql must not have columns

Error message

Insert sql must not have columns

What it means

Thrown by parseInsertSql when an INSERT INTO statement specifies an explicit column list. The SeaTunnel SQL config dialect only supports 'INSERT INTO sink SELECT ...' without enumerating columns; column mapping must be handled by the SELECT projection.

Source

Thrown at seatunnel-config/seatunnel-config-sql/src/main/java/org/apache/seatunnel/config/sql/SqlConfigBuilder.java:364

            String query = select.toString();
            transformConfig.setPluginInputIdentifier(pluginInputIdentifier);
            transformConfig.setPluginOutputIdentifier(pluginOutputIdentifier);
            transformConfig.setQuery(query);

            return transformConfig;
        } else {
            throw new ParserException(String.format("Unsupported syntax: %s", createTable));
        }
    }

    private static void parseInsertSql(
            Insert insertSql,
            Map<String, BaseConfig> sqlTables,
            SeaTunnelConfig seaTunnelConfig,
            AtomicInteger tempTableIndex) {
        if (insertSql.getColumns() != null && !insertSql.getColumns().isEmpty()) {
            throw new ParserException("Insert sql must not have columns");
        }
        TransformConfig transformConfig = new TransformConfig();
        Select select = insertSql.getSelect();
        if (select == null
                || select.getSelectBody() == null
                || !(select.getSelectBody() instanceof PlainSelect)) {
            throw new ParserException("Insert sql must have select statement");
        }
        String targetTableName = insertSql.getTable().getName();
        if (select.getSelectBody() instanceof PlainSelect) {
            PlainSelect plainSelect = (PlainSelect) select.getSelectBody();

            String pluginInputIdentifier;
            String pluginOutputIdentifier;
            if (plainSelect.getFromItem() == null) {
                List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
                if (selectItems.size() != 1) {
                    throw new ParserException(

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove the column list and rely on the SELECT item order/projection
  2. Reorder or alias columns inside the SELECT clause to achieve the desired mapping

Example fix

// before
INSERT INTO sink_t (a, b) SELECT x, y FROM src
// after
INSERT INTO sink_t SELECT x AS a, y AS b FROM src
Defensive patterns

Strategy: validation

Validate before calling

// reject INSERT column lists before building config
if (sql.toLowerCase().matches(".*insert\\s+into\\s+\\w+\\s*\\(.*")) {
    throw new IllegalArgumentException("INSERT INTO must not list columns; map columns in the SELECT projection");
}

Try / catch

try {
    SeaTunnelConfig c = SqlConfigBuilder.of(sql);
} catch (ParserException e) {
    if (e.getMessage().equals("Insert sql must not have columns")) {
        // move column mapping into SELECT aliases
    }
}

Prevention

When it happens

Trigger: INSERT INTO sink_t (a, b) SELECT ... — any non-empty column list on the INSERT target triggers this.

Common situations: Users porting standard ANSI SQL from Flink/Spark where column lists are common; attempting column reordering via the INSERT clause.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/3da6a2bd3428c415. Report an issue: GitHub.