apache/seatunnel · critical · RuntimeException

Can't obtain schema for table %s

Error message

Can't obtain schema for table %s

What it means

After both the information-schema load and the `DESC` fallback, readTableSchema checks that tableChangeMap contains the requested TableId. If not, it throws RuntimeException 'Can't obtain schema for table <id>' — meaning schema was loaded but the target table is absent from the result.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/utils/MySqlSchema.java:102

        try {
            tableChangeMap = getTableSchemaByShowCreateTable(jdbc, tableId);
            if (tableChangeMap.isEmpty()) {
                log.debug("Load schema is empty for table {}", tableId);
            }
        } catch (Exception e) {
            log.debug("Ignore exception when execute `SHOW CREATE TABLE {}` failed", tableId, e);
        }
        if (tableChangeMap.isEmpty()) {
            try {
                log.info("Fallback to use `DESC {}` load schema", tableId);
                tableChangeMap = getTableSchemaByDescTable(jdbc, tableId);
            } catch (SQLException ex) {
                throw new SeaTunnelException(
                        String.format("Failed to read schema for table %s", tableId), ex);
            }
        }
        if (!tableChangeMap.containsKey(tableId)) {
            throw new RuntimeException(String.format("Can't obtain schema for table %s", tableId));
        }

        return tableChangeMap.get(tableId);
    }

    @VisibleForTesting
    public TableChange readTableSchemaByDesc(JdbcConnection jdbc, TableId tableId) {
        try {
            return getTableSchemaByDescTable(jdbc, tableId).get(tableId);
        } catch (SQLException ex) {
            throw new SeaTunnelException(
                    String.format("Failed to read schema for table %s", tableId), ex);
        }
    }

    private Map<TableId, TableChange> getTableSchemaByShowCreateTable(
            JdbcConnection jdbc, TableId tableId) throws SQLException {
        AtomicReference<String> ddl = new AtomicReference<>();

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Confirm the exact table name/case as MySQL sees it (`SELECT table_schema, table_name FROM information_schema.tables WHERE lower(table_name)=...`)
  2. Re-check the table exists at job start; recreate or restore it if dropped
  3. Use fully-qualified, correctly-quoted table names in the SeaTunnel catalog/table config
  4. Align lower_case_table_names expectations between config and server

Example fix

// before
{"table-names": ["MYDB.MYTABLE"]}
// after
{"table-names": ["mydb.mytable"]} // exact case as in MySQL
Defensive patterns

Strategy: validation

Validate before calling

SELECT table_schema, table_name FROM information_schema.tables
WHERE table_schema='mydb' AND BINARY table_name='mytable';
// must return exactly one row matching your config

Try / catch

try {
    startCdcJob(config);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Can't obtain schema for table")) {
        log.error("Schema loaded but table missing from result; verify exact identifier case");
    }
}

Prevention

When it happens

Trigger: getTableSchema where getTableSchemaByDescTable succeeded but the returned map does not contain the exact TableId (name/case mismatch) or both loaders returned no schema for it.

Common situations: Case-mismatched database/table identifiers on case-sensitive filesystems; table deleted after job planning; catalog qualifier differences (quoted identifiers) between information schema and DESC output.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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