apache/seatunnel · error · ParserException

Table name duplicate: %s

Error message

Table name duplicate: %s

What it means

parseCreateTableSql rejects duplicate table names: if a second CREATE TABLE declares a name already present in sqlTables, it throws ParserException 'Table name duplicate'. Each table name in a seatunnel SQL config must be unique because names are used as map keys and as plugin_input/plugin_output identifiers.

Source

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

                sqlList.add(sqlSj.toString());
                sqlSj = new StringJoiner(" ");
            } else {
                sqlSj.add(line);
            }
        }
        return sqlList;
    }

    private static void parseCreateTableSql(
            CreateTable createTable,
            Map<String, BaseConfig> sqlTables,
            SeaTunnelConfig seaTunnelConfig) {

        Map<String, String> optionsMap = parseOptions(createTable);

        String tableName = createTable.getTable().getName();
        if (sqlTables.containsKey(tableName)) {
            throw new ParserException(String.format("Table name duplicate: %s", tableName));
        }
        String type = optionsMap.get(OPTION_TABLE_TYPE_KEY);
        if (OPTION_TABLE_TYPE_SOURCE.equalsIgnoreCase(type)) {
            SourceConfig sourceConfig = parseSourceSql(createTable, optionsMap);
            sqlTables.put(tableName, sourceConfig);
            seaTunnelConfig.getSourceConfigs().add(sourceConfig);
        } else if (OPTION_TABLE_TYPE_SINK.equalsIgnoreCase(type)) {
            SinkConfig sinkConfig = parseSinkSql(optionsMap);
            sqlTables.put(tableName, sinkConfig);
            seaTunnelConfig.getSinkConfigs().add(sinkConfig);
        }
    }

    private static Map<String, String> parseOptions(CreateTable createTable) {
        String options = createTable.getTableOptionsStrings().get(1);
        options = options.substring(0, options.length() - 1).substring(1);
        String[] optionItems = options.split(OPTION_DELIMITER);
        Map<String, String> optionsMap = new LinkedHashMap<>();

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Rename one of the duplicate tables and update the INSERT ... SELECT references.
  2. Delete the stale duplicate CREATE TABLE definition.
  3. Use distinct table names and distinct plugin_output identifiers per connector instance.
  4. Unify options into one table instead of redefining it with different WITH options.

Example fix

// before
CREATE TABLE src WITH ('connector'='fake', 'type'='source') (id INT);
CREATE TABLE src WITH ('connector'='kafka', 'type'='source') (id INT); -- duplicate
// after
CREATE TABLE src_fake WITH ('connector'='fake', 'type'='source') (id INT);
CREATE TABLE src_kafka WITH ('connector'='kafka', 'type'='source') (id INT);
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (String line : lines) {
    Matcher m = Pattern.compile("CREATE TABLE\\s+(\\w+)").matcher(line);
    if (m.find() && !seen.add(m.group(1))) throw new IllegalStateException("Duplicate table: " + m.group(1));
}

Try / catch

try { Config c = SqlConfigBuilder.of(sqlFile); } catch (ParserException e) { if (e.getMessage().startsWith("Table name duplicate")) { /* rename/delete the table named in the message */ } }

Prevention

When it happens

Trigger: Declaring two CREATE TABLE statements with the same name (e.g. redefining a source with different options), or accidentally copy-pasting a table block twice in the .sql file.

Common situations: Merging multiple config files where each declares the same table, iterating a config generator that emits the old definition twice, defining two sources but reusing one name instead of distinct names.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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