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
- Remove the column list and rely on the SELECT item order/projection
- 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
- Always write INSERT INTO <table> SELECT ... without a column list
- Use SELECT aliases (expr AS col) for column mapping/reordering
- Lint for the pattern 'INSERT INTO t (' in scripts
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
- Insert sql must have select statement
- Unsupported syntax: <insertSql>
- Unsupported syntax: %s
- Source table must be specified in SQL: <insertSql>
- The sink table[%s] is not found
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/3da6a2bd3428c415.
Report an issue: GitHub.