apache/seatunnel · error · SeaTunnelException
Failed to read schema for table
Error message
Failed to read schema for table %s
What it means
MySqlSchema.readTableSchemaByDesc wraps any SQLException raised while reading a table's schema via `DESC <table>` into a SeaTunnelException with this message. The library throws it because schema discovery (needed for CDC type mapping) failed at the JDBC level; the original SQLException is preserved as the cause. It indicates the connector could not introspect the table structure, not a data-read problem.
Solutions
- Verify the table still exists in MySQL (SHOW TABLES / DESC the table manually) and recreate or exclude it if dropped
- Grant the CDC user schema-introspection privileges (SELECT on the table plus metadata access) and rerun
- Check JDBC connectivity to MySQL (network, firewall, server uptime) and retry the job
- Inspect the wrapped SQLException cause for the exact MySQL error code and address it specifically
Example fix
// before
TableChange change = schema.readTableSchemaByDesc(jdbc, tableId);
// after
try {
TableChange change = schema.readTableSchemaByDesc(jdbc, tableId);
} catch (SeaTunnelException e) {
LOG.warn("Table {} unavailable for CDC, skipping", tableId, e.getCause());
} Defensive patterns
Strategy: try-catch
Validate before calling
try (Statement st = conn.createStatement()) {
ResultSet rs = st.executeQuery("DESC `" + table + "`");
if (!rs.next()) throw new IllegalStateException("Table " + table + " not readable");
} Type guard
boolean tableReadable(Connection c, String table) {
try (ResultSet rs = c.createStatement().executeQuery(
"SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='" + table + "'")) {
return rs.next();
} catch (SQLException e) { return false; }
} Try / catch
try {
TableChange change = schema.readTableSchemaByDesc(jdbc, tableId);
} catch (SeaTunnelException e) {
if (e.getCause() instanceof SQLException) { /* log cause, skip or fail table */ }
} Prevention
- Grant the CDC user DESC/metadata privileges on all listed tables
- Exclude volatile/temporary tables from the CDC table list
- Keep JDBC connections alive (proper timeouts, no aggressive firewall idle kills)
- Pre-check table existence before starting the job
When it happens
Trigger: Calling readTableSchemaByDesc (via tableChangeByDesc) when the DESCRIBE statement against MySQL fails: table dropped/renamed between discovery and schema read, insufficient privileges (no DESC permission), connection broken, or MySQL server error during query execution.
Common situations: CDC job reads a table that was dropped mid-job; a user with only SELECT on some tables tries to snapshot others; network drop or MySQL restart during schema read; firewall/proxy killing idle JDBC connections.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Database configuration option
- Error reading default database charsets:
- Error reading default database charsets
- Error reading MySQL variables:
- Error reading MySQL variables
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b80b23c1c404db08.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/utils/MySqlSchema.java:113
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<>();
String sql = SHOW_CREATE_TABLE + MySqlUtils.quote(tableId);
jdbc.query(
sql,
rs -> {
rs.next();
ddl.set(rs.getString(2));
});
return parseSnapshotDdl(tableId, ddl.get());
}
private Map<TableId, TableChange> getTableSchemaByDescTable(View on GitHub (pinned to cf67b549a7)