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

  1. Verify the table still exists in MySQL (SHOW TABLES / DESC the table manually) and recreate or exclude it if dropped
  2. Grant the CDC user schema-introspection privileges (SELECT on the table plus metadata access) and rerun
  3. Check JDBC connectivity to MySQL (network, firewall, server uptime) and retry the job
  4. 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

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


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)