apache/seatunnel · error · DebeziumException
Oracle failed to re-construct redo SQL
Error message
Oracle failed to re-construct redo SQL '${redoSql}' What it means
When processing a LogMiner row with STATUS=2 and a non-blank INFO column, the SQL_REDO produced by LogMiner is not valid and cannot be parsed into an event. Depending on event.processing.failure.handling.mode, the FAIL mode throws this DebeziumException, aborting the connector. LogMiner sometimes emits such rows for unsupported internal operations or DDL-adjacent changes.
Solutions
- Set event.processing.failure.handling.mode=WARN (or SKIP) so unparseable STATUS=2 events are logged and skipped instead of failing the connector.
- Inspect the logged row (table, INFO column) to identify the unsupported Oracle operation and exclude it (table filters) if it's not needed.
- Upgrade the Debezium/connector version — many STATUS=2 handling gaps are fixed over time.
- If the redo stream is genuinely corrupted, resnapshot the database and restart from a clean SCN.
Example fix
// before: connector stops on unparseable redo SQL "event.processing.failure.handling.mode": "fail" // after: log and skip the problematic event "event.processing.failure.handling.mode": "warn"
Defensive patterns
Strategy: try-catch
Try / catch
try {
processRow(row);
} catch (DebeziumException e) {
if (e.getMessage().startsWith("Oracle failed to re-construct redo SQL")) {
LOGGER.warn("Skipping unparseable LogMiner row: {}", row);
} else { throw e; }
} Prevention
- Set event.processing.failure.handling.mode=warn for noisy production Oracle schemas
- Keep the connector and Oracle server versions compatible
- Review LogMiner INFO/STATUS diagnostics for recurring unsupported operations
- Maintain an alert on skipped-event counts so silent data loss is visible
When it happens
Trigger: handleDataEvent (called from processRow) sees row.getStatus()==2 with non-blank row.getInfo() while event.processing.failure.handling.mode=FAIL — the redo SQL string cannot be re-constructed into valid SQL by LogMiner.
Common situations: Oracle internal operations LogMiner can't translate (e.g. certain dictionary maintenance, temporary/cluster operations); corrupted or partial redo SQL after instance recovery; mining across versions with unsupported data types; events logged with INFO diagnostics by Oracle.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- DML statement couldn't be parsed. Please open a Jira issue…
- Unable to parse unsupported LOB_WRITE SQL
- Cannot get maximum archive log SCN as no archive logs are…
- Cannot get maximum archive log SCN as no logs were…
- Failed to calculate oldest SCN available in logs
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/9416ffb9b28dd35b.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/io/debezium/connector/oracle/logminer/processor/AbstractLogMinerEventProcessor.java:812
*/
protected void handleDataEvent(LogMinerEventRow row) throws SQLException, InterruptedException {
if (row.getRedoSql() == null) {
return;
}
LOGGER.trace("DML: {}", row);
LOGGER.trace("\t{}", row.getRedoSql());
// Oracle LogMiner reports LONG data types as STATUS=2 on UPDATE statements but there is no
// value in the INFO column, and the record can be managed by the connector successfully,
// so to be backward compatible, we only explicitly trigger this behavior if there is an
// error reason for STATUS=2 in the INFO column as well as STATUS=2.
if (row.getStatus() == 2 && !Strings.isNullOrBlank(row.getInfo())) {
// The SQL in the SQL_REDO column is not valid and cannot be parsed.
switch (connectorConfig.getEventProcessingFailureHandlingMode()) {
case FAIL:
LOGGER.error("Oracle LogMiner is unable to re-construct the SQL for '{}'", row);
throw new DebeziumException(
"Oracle failed to re-construct redo SQL '" + row.getRedoSql() + "'");
case WARN:
LOGGER.warn(
"Oracle LogMiner event '{}' cannot be parsed. This event will be ignored and skipped.",
row);
return;
default:
// In this case, we explicitly log the situation in "debug" only and not as an
// error/warn.
LOGGER.debug(
"Oracle LogMiner event '{}' cannot be parsed. This event will be ignored and skipped.",
row);
return;
}
}
counters.dmlCount++;
switch (row.getEventType()) {View on GitHub (pinned to cf67b549a7)