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

  1. Add 'FROM source_table' and move constants/literals into the SELECT projection
  2. When using the no-FROM shorthand, keep exactly one select item that is the source table name
  3. 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

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


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