{"record":{"id":"95293c5f5f385fca","repo":"apache/seatunnel","slug":"unsupported-restored-pendingsplitsstate-check","errorCode":null,"errorMessage":"Unsupported restored PendingSplitsState: \" + checkpointState","messagePattern":"Unsupported restored PendingSplitsState: \" \\+ checkpointState","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/IncrementalSource.java","lineNumber":421,"sourceCode":"                            checkpointSnapshotState.getSplitCompletedOffsets());\n            splitAssigner =\n                    new SnapshotOnlySplitAssigner<>(\n                            assignerContext,\n                            enumeratorContext.currentParallelism(),\n                            checkpointSnapshotState,\n                            dataSourceDialect);\n        } else if (checkpointState instanceof IncrementalPhaseState) {\n            SplitAssigner.Context<C> assignerContext =\n                    new SplitAssigner.Context<>(\n                            sourceConfig, capturedTables, new HashMap<>(), new HashMap<>());\n            splitAssigner =\n                    new IncrementalSplitAssigner<>(\n                            assignerContext,\n                            incrementalParallelism,\n                            offsetFactory,\n                            (IncrementalPhaseState) checkpointState);\n        } else {\n            throw new UnsupportedOperationException(\n                    \"Unsupported restored PendingSplitsState: \" + checkpointState);\n        }\n        return new IncrementalSourceEnumerator(enumeratorContext, splitAssigner);\n    }\n\n    private HybridPendingSplitsState restore(\n            Set<TableId> capturedTables, HybridPendingSplitsState checkpointState) {\n        SnapshotPhaseState checkpointSnapshotState = checkpointState.getSnapshotPhaseState();\n        Set<TableId> checkpointCapturedTables =\n                Stream.concat(\n                                checkpointSnapshotState.getAlreadyProcessedTables().stream(),\n                                checkpointSnapshotState.getRemainingTables().stream())\n                        .collect(Collectors.toSet());\n        Set<TableId> newTables = Sets.difference(capturedTables, checkpointCapturedTables);\n        Set<TableId> deletedTables = Sets.difference(checkpointCapturedTables, capturedTables);\n\n        checkpointSnapshotState.getRemainingTables().addAll(newTables);\n        checkpointSnapshotState.getRemainingTables().removeAll(deletedTables);","sourceCodeStart":403,"sourceCodeEnd":439,"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/IncrementalSource.java#L403-L439","documentation":"IncrementalSource.restoreEnumerator reconstructs a split assigner from a restored PendingSplitsState. It supports specific state classes (e.g. HybridPendingSplitsState / IncrementalPhaseState); any other restored state type is rejected with UnsupportedOperationException naming the offending checkpointState object.","triggerScenarios":"restoreEnumerator is called with a checkpoint whose PendingSplitsState instance is neither of the supported types — typically a checkpoint produced by a different connector type or an incompatible SeaTunnel/connector-cdc version.","commonSituations":"Restoring a CDC job's savepoint after an engine or connector upgrade that changed the state class layout, or restoring a state saved by a different source factory (e.g. pure snapshot source) into an incremental source.","solutions":["Use a checkpoint/savepoint created by the exact same SeaTunnel and connector-cdc version","If the state is from an incompatible version, restart the job without restore (fresh run) instead of restoring","Do not share checkpoints between different CDC connector types (e.g. MySQL vs Postgres CDC)","Check restoredState class in logs to confirm which type was actually saved"],"exampleFix":"// before\n// restore incremental CDC source from a checkpoint saved by connector-cdc version 2.3.4 on engine 2.3.8\nbin/seatunnel.sh --config job.conf -r mixed-version-checkpoint\n// after\nbin/seatunnel.sh --config job.conf -r matching-version-savepoint  // same engine+connector version\n// or restart fresh\nbin/seatunnel.sh --config job.conf","handlingStrategy":"fallback","validationCode":"// guard restore by checking state type compatibility\nif (!(checkpointState instanceof HybridPendingSplitsState) && !(checkpointState instanceof IncrementalPhaseState)) {\n    throw new IllegalStateException(\"Incompatible PendingSplitsState for restore: \" + checkpointState.getClass());\n}","typeGuard":null,"tryCatchPattern":"try {\n    enumerator = source.restoreEnumerator(context, checkpointState);\n} catch (UnsupportedOperationException e) {\n    // fall back to a fresh run without restore\n}","preventionTips":["Never restore checkpoints across SeaTunnel/connector version upgrades without a migration plan","Keep checkpoints per source type — do not reuse across connector types","Log checkpointState class name in operational tooling before restore"],"tags":["cdc","checkpoint","restore","state-compatibility"],"backgroundTag":"incompatible-source-type","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"}