apache/seatunnel · error · IllegalArgumentException
Invalid table name: ${tableStr} ,Postgres identifier is of t
Error message
Invalid table name: ${tableStr} ,Postgres identifier is of the form schemaName.tableName What it means
PostgresSourceConfigFactory.create parses each table-list entry expecting 2 or 3 dot-separated parts (schema.table or db.schema.table). Any other shape (wrong number of parts) fails fast with IllegalArgumentException because a valid PostgreSQL identifier must resolve to schemaName.tableName.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/config/PostgresSourceConfigFactory.java:101
if (schemaList != null) {
props.setProperty("schema.include.list", String.join(",", schemaList));
}
if (tableList != null) {
// pg identifier is of the form schemaName.tableName
props.setProperty(
"table.include.list",
tableList.stream()
.map(
tableStr -> {
String[] splits = tableStr.split("\\.");
if (splits.length == 2) {
return tableStr;
}
if (splits.length == 3) {
return String.join(".", splits[1], splits[2]);
}
throw new IllegalArgumentException(
"Invalid table name: "
+ tableStr
+ " ,Postgres identifier is of the form schemaName.tableName");
})
.collect(Collectors.joining(",")));
}
if (dbzProperties != null) {
props.putAll(dbzProperties);
}
// Debezium PostgreSQL does not emit DDL records, but SeaTunnel uses this flag to enable
// synthetic schema records produced from pgoutput RELATION messages. Apply it after the
// Debezium pass-through properties so the SeaTunnel option remains authoritative.
props.setProperty("include.schema.changes", String.valueOf(schemaChangeEnabled));
if (startupConfig != null && startupConfig.getStartupMode() == StartupMode.SNAPSHOT_ONLY) {
props.setProperty("snapshot.mode", "initial_only");
} else if (startupConfig != null
&& startupConfig.getStartupMode() == StartupMode.COMMITTED_OFFSET) {View on GitHub (pinned to cf67b549a7)
Solutions
- Use fully qualified 'schemaName.tableName' (e.g. public.orders) in table-names.
- If you must use database.schema.table, ensure exactly 3 parts so the first is stripped.
- Quote identifiers containing dots or mixed case with double quotes per Postgres rules.
- Check for typos like trailing dots or spaces that create empty parts.
Example fix
// before table-names = ["orders"] // after table-names = ["public.orders"]
Defensive patterns
Strategy: validation
Validate before calling
boolean isValid = tableStr.matches("([^.]+\\.)?[^.]+\\.[^.]+"); // schema.table or db.schema.table
if (!isValid) throw new IllegalArgumentException("Use schemaName.tableName: " + tableStr); Prevention
- Always write table-names as 'schema.table' (usually public.<table>).
- Quote identifiers that contain dots or mixed case.
- Lint configs for empty segments before deployment.
When it happens
Trigger: table-names entry with 1 part (e.g. 'mytable'), more than 3 parts, or 3 parts where dropping the first is wrong — thrown during create() called by PostgresDialect, LsnOffsetFactory and startup-offset validation.
Common situations: Users passing just a table name without schema; copying MySQL-style identifiers; unquoted names containing dots; region-qualified 'catalog.schema.table' confusion.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Publication autocreation is disabled, please create one and
- No table filters found for filtered publication %s
- Table ${tableId} does not have a full replica identity, plea
- PostgreSQL-CDC startup.mode 'COMMITTED_OFFSET' requires an e
- Incremental snapshot for tables requires primary key, but ta
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b2de2d2f87878847.
Report an issue: GitHub.