apache/seatunnel · error · ParserException
Source table must be specified in SQL: <insertSql>
Error message
Source table must be specified in SQL: <insertSql>
What it means
Thrown by parseInsertSql when a SELECT without a FROM clause does not consist of exactly one select item. The dialect supports 'INSERT INTO sink SELECT column_name' (bare table-name-as-column shorthand) but only with a single expression, and it must be a Column.
Source
Thrown at seatunnel-config/seatunnel-config-sql/src/main/java/org/apache/seatunnel/config/sql/SqlConfigBuilder.java:382
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(
"Source table must be specified in SQL: " + insertSql);
}
SelectItem<?> selectItem = selectItems.get(0);
Column column = (Column) selectItem.getExpression();
pluginInputIdentifier = column.getColumnName();
pluginOutputIdentifier = pluginInputIdentifier;
} else {
if (!(plainSelect.getFromItem() instanceof Table)) {
throw new ParserException("Unsupported syntax: " + insertSql);
}
Table table = (Table) plainSelect.getFromItem();
pluginInputIdentifier = table.getName();
pluginOutputIdentifier =
pluginInputIdentifier
+ TEMP_TABLE_SUFFIX
+ tempTableIndex.getAndIncrement();
String query = select.toString();
transformConfig.setPluginInputIdentifier(pluginInputIdentifier);View on GitHub (pinned to cf67b549a7)
Solutions
- Add 'FROM source_table' and move constants/literals into the SELECT projection
- When using the no-FROM shorthand, keep exactly one select item that is the source table name
- Split constant generation into a dedicated source table instead
Example fix
// before INSERT INTO sink_t SELECT 1, 'a' // after INSERT INTO sink_t SELECT 1, 'a' FROM fake_source
Defensive patterns
Strategy: validation
Validate before calling
// for FROM-less SELECT in INSERT, require exactly one column item
Pattern p = Pattern.compile("(?si)INSERT\\s+INTO\\s+\\w+\\s+SELECT\\s+([^\\s;]+)\\s*;");
// if SELECT has no FROM, ensure it has a single plain column reference Try / catch
try {
SeaTunnelConfig c = SqlConfigBuilder.of(sql);
} catch (ParserException e) {
if (e.getMessage().startsWith("Source table must be specified")) {
// add 'FROM source_table' to the INSERT SELECT
}
} Prevention
- Always include FROM in INSERT SELECT queries; use the bare-table-name shorthand only for single-column passthrough
- Never mix literals with the no-FROM shorthand
- Prefer explicit source tables over FROM-less expressions
When it happens
Trigger: INSERT INTO sink_t SELECT 1 (no FROM and multiple/complex expressions); INSERT ... SELECT a, b with no FROM; a non-column expression like a function call in the no-FROM form.
Common situations: Trying constant-only inserts (SELECT 1,'x') without a FROM; adding extra literals alongside the source-table shorthand.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Insert sql must not have columns
- Insert sql must have select statement
- Unsupported syntax: <insertSql>
- The sink table[%s] is not found
- The source table[%s] is not found
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/bcde2292d756af10.
Report an issue: GitHub.