{"record":{"id":"a1bfac01adaaee59","repo":"apache/seatunnel","slug":"the-table-changes-should-only-have-one-element","errorCode":null,"errorMessage":"The table changes should only have one element","messagePattern":"The table changes should only have one element","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/reader/external/JdbcSourceFetchTaskContext.java","lineNumber":199,"sourceCode":"                    dataSourceDialect.queryTableSchema(connection, snapshotSplit.getTableId()));\n        } else {\n            IncrementalSplit incrementalSplit = (IncrementalSplit) sourceSplitBase;\n            Map<TableId, byte[]> historyTableChanges = incrementalSplit.getHistoryTableChanges();\n            for (TableId tableId : incrementalSplit.getTableIds()) {\n                if (historyTableChanges != null && historyTableChanges.containsKey(tableId)) {\n                    SchemaAndValue schemaAndValue =\n                            jsonConverter.toConnectData(\"topic\", historyTableChanges.get(tableId));\n                    Struct deserializedStruct = (Struct) schemaAndValue.value();\n\n                    TableChanges tableChanges =\n                            tableChangeSerializer.deserialize(\n                                    Collections.singletonList(deserializedStruct), false);\n\n                    Iterator<TableChanges.TableChange> iterator = tableChanges.iterator();\n                    TableChanges.TableChange tableChange = null;\n                    while (iterator.hasNext()) {\n                        if (tableChange != null) {\n                            throw new IllegalStateException(\n                                    \"The table changes should only have one element\");\n                        }\n                        tableChange = iterator.next();\n                    }\n                    engineHistory.add(tableChange);\n                    continue;\n                }\n                engineHistory.add(dataSourceDialect.queryTableSchema(connection, tableId));\n            }\n        }\n\n        EmbeddedDatabaseHistory.registerHistory(\n                sourceConfig\n                        .getDbzConfiguration()\n                        .getString(EmbeddedDatabaseHistory.DATABASE_HISTORY_INSTANCE_NAME),\n                engineHistory);\n    }\n","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/reader/external/JdbcSourceFetchTaskContext.java#L181-L217","documentation":"registerDatabaseHistory replays a schema-change event through Debezium's schema history and expects exactly one TableChange per deserialized Struct. If iterating the produced TableChanges yields a second element, the invariant 'one schema change event -> one table change' is broken and IllegalStateException is thrown. This guards against corrupted or multi-table history records during schema-history recovery.","triggerScenarios":"During database schema history registration, deserializing a history record produces more than one TableChange, e.g. a malformed or duplicated schema history entry in the database-history storage (file/Kafka topic).","commonSituations":"Corrupted or hand-edited schema history file shared by multiple jobs; schema history topic reused across different jobs/databases; upgrading Debezium changed the history record format so old records deserialize into extra changes; concurrent writers appending to the same history storage.","solutions":["Reset the database schema history storage (delete the history file / use a fresh history topic) and restart the job so the schema history is rebuilt from snapshot.","Ensure each SeaTunnel CDC job has its own dedicated schema history storage; never share the history topic/file across jobs.","Check Debezium version compatibility; if the history format changed, rebuild history with the matching Debezium version.","Keep a backup of the history file before edits; corruption here is the usual trigger."],"exampleFix":"// before: shared history file\nschema-history.file = /data/dbhistory.dat  // shared by jobs\n// after: per-job history file\nschema-history.file = /data/dbhistory-${job.id}.dat","handlingStrategy":"fallback","validationCode":"// verify history storage is dedicated and unmodified\n// one history file/topic per job; check file size growth is monotonic","typeGuard":null,"tryCatchPattern":"try {\n    registerDatabaseHistory(struct);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"one element\")) {\n        // rebuild schema history from a fresh snapshot\n    }\n}","preventionTips":["Give each CDC job its own schema-history file/topic.","Never hand-edit schema history storage.","Back up history storage before Debezium/connector upgrades."],"tags":["cdc","schema-history","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-14T05:17:10.506Z"}