{"record":{"id":"31dc70b1b64c1b0f","repo":"apache/seatunnel","slug":"the-update-before-event-at-position-for-table","errorCode":null,"errorMessage":"The update before event at ${position} for table ${tableId} was not followed by after event.\n Please report this as a bug together with a events around given LSN.","messagePattern":"The update before event at (.+?) for table (.+?) was not followed by after event\\.\n Please report this as a bug together with a events around given LSN\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/io/debezium/connector/sqlserver/SqlServerStreamingChangeEventSource.java","lineNumber":428,"sourceCode":"                                    final TableId tableId =\n                                            tableWithSmallestLsn\n                                                    .getChangeTable()\n                                                    .getSourceTableId();\n                                    final int operation = tableWithSmallestLsn.getOperation();\n                                    final Object[] data = tableWithSmallestLsn.getData();\n\n                                    // UPDATE consists of two consecutive events, first event\n                                    // contains\n                                    // the row before it was updated and the second the row after\n                                    // it was updated\n                                    int eventCount = 1;\n                                    if (operation\n                                            == SqlServerChangeRecordEmitter.OP_UPDATE_BEFORE) {\n                                        if (!tableWithSmallestLsn.next()\n                                                || tableWithSmallestLsn.getOperation()\n                                                        != SqlServerChangeRecordEmitter\n                                                                .OP_UPDATE_AFTER) {\n                                            throw new IllegalStateException(\n                                                    \"The update before event at \"\n                                                            + tableWithSmallestLsn\n                                                                    .getChangePosition()\n                                                            + \" for table \"\n                                                            + tableId\n                                                            + \" was not followed by after event.\\n Please report this as a bug together with a events around given LSN.\");\n                                        }\n                                        eventCount = 2;\n                                    }\n                                    final Object[] dataNext =\n                                            (operation\n                                                            == SqlServerChangeRecordEmitter\n                                                                    .OP_UPDATE_BEFORE)\n                                                    ? tableWithSmallestLsn.getData()\n                                                    : null;\n\n                                    offsetContext.setChangePosition(\n                                            tableWithSmallestLsn.getChangePosition(), eventCount);","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/io/debezium/connector/sqlserver/SqlServerStreamingChangeEventSource.java#L410-L446","documentation":"An IllegalStateException raised by the SQL Server CDC streaming reader when it dequeues an UPDATE_BEFORE change record but the next record is not the matching UPDATE_AFTER for the same table/LSN. Debezium's contract requires update pairs; breaking it indicates corrupted CDC capture or a reader bug.","triggerScenarios":"During streamedEvent iteration: the merge-heap (tableWithSmallestLsn) returns OP_UPDATE_BEFORE whose next entry differs in operation or table, typically because CDC capture tables were partially cleaned or an LSN was skipped while polling.","commonSituations":"sys.cdc cleanup job removing rows between the before/after reads; concurrent capture-instance changes (disable/enable CDC) while streaming; reading across an AG failover; a genuine Debezium bug — the message asks you to report it with surrounding LSN events.","solutions":["Report to SeaTunnel/Debezium with the position and surrounding LSN events as the message instructs","Check the SQL Server CDC capture job (sys.cdc jobs) — pause cdc.db_capture cleanup or increase retention","Ensure no CDC instance was disabled/altered for the table during streaming","Re-snapshot the affected table (restart job from snapshot) to restore a consistent stream","Upgrade to the latest Debezium/SeaTunnel CDC version where pairing bugs may be fixed"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"-- before streaming, ensure capture jobs are healthy and retention is sufficient\nSELECT name, retention, pollinterval FROM msdb.dbo.cdc_jobs;","typeGuard":null,"tryCatchPattern":"catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"was not followed by after event\")) {\n        LOG.error(\"CDC update-pair invariant broken; resnapshot the table\", e);\n        // restart job from snapshot\n    }\n    throw e;\n}","preventionTips":["Increase CDC retention / disable the aggressive cleanup job during long streams","Never disable or alter CDC capture instances while a stream is active","Avoid AG failovers mid-stream or restart from snapshot after one","Keep the Debezium/SeaTunnel CDC connector version current"],"tags":["sqlserver","cdc","debezium","data-corruption"],"backgroundTag":"internal-invariant-violation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}