{"record":{"id":"9416ffb9b28dd35b","repo":"apache/seatunnel","slug":"oracle-failed-to-re-construct-redo-sql-redosql","errorCode":null,"errorMessage":"Oracle failed to re-construct redo SQL '${redoSql}'","messagePattern":"Oracle failed to re-construct redo SQL '(.+?)'","errorType":"exception","errorClass":"DebeziumException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/io/debezium/connector/oracle/logminer/processor/AbstractLogMinerEventProcessor.java","lineNumber":812,"sourceCode":"     */\n    protected void handleDataEvent(LogMinerEventRow row) throws SQLException, InterruptedException {\n        if (row.getRedoSql() == null) {\n            return;\n        }\n\n        LOGGER.trace(\"DML: {}\", row);\n        LOGGER.trace(\"\\t{}\", row.getRedoSql());\n\n        // Oracle LogMiner reports LONG data types as STATUS=2 on UPDATE statements but there is no\n        // value in the INFO column, and the record can be managed by the connector successfully,\n        // so to be backward compatible, we only explicitly trigger this behavior if there is an\n        // error reason for STATUS=2 in the INFO column as well as STATUS=2.\n        if (row.getStatus() == 2 && !Strings.isNullOrBlank(row.getInfo())) {\n            // The SQL in the SQL_REDO column is not valid and cannot be parsed.\n            switch (connectorConfig.getEventProcessingFailureHandlingMode()) {\n                case FAIL:\n                    LOGGER.error(\"Oracle LogMiner is unable to re-construct the SQL for '{}'\", row);\n                    throw new DebeziumException(\n                            \"Oracle failed to re-construct redo SQL '\" + row.getRedoSql() + \"'\");\n                case WARN:\n                    LOGGER.warn(\n                            \"Oracle LogMiner event '{}' cannot be parsed. This event will be ignored and skipped.\",\n                            row);\n                    return;\n                default:\n                    // In this case, we explicitly log the situation in \"debug\" only and not as an\n                    // error/warn.\n                    LOGGER.debug(\n                            \"Oracle LogMiner event '{}' cannot be parsed. This event will be ignored and skipped.\",\n                            row);\n                    return;\n            }\n        }\n\n        counters.dmlCount++;\n        switch (row.getEventType()) {","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/io/debezium/connector/oracle/logminer/processor/AbstractLogMinerEventProcessor.java#L794-L830","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: connector stops on unparseable redo SQL\n\"event.processing.failure.handling.mode\": \"fail\"\n// after: log and skip the problematic event\n\"event.processing.failure.handling.mode\": \"warn\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    processRow(row);\n} catch (DebeziumException e) {\n    if (e.getMessage().startsWith(\"Oracle failed to re-construct redo SQL\")) {\n        LOGGER.warn(\"Skipping unparseable LogMiner row: {}\", row);\n    } else { throw e; }\n}","preventionTips":["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"],"tags":["oracle","cdc","logminer","redo-sql","event-processing"],"backgroundTag":"invalid-argument-format","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}