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

  1. Set event.processing.failure.handling.mode=WARN (or SKIP) so unparseable STATUS=2 events are logged and skipped instead of failing the connector.
  2. Inspect the logged row (table, INFO column) to identify the unsupported Oracle operation and exclude it (table filters) if it's not needed.
  3. Upgrade the Debezium/connector version — many STATUS=2 handling gaps are fixed over time.
  4. 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

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


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)