{"record":{"id":"cfc0f87e69e70278","repo":"apache/seatunnel","slug":"the-single-split-reader-don-t-support-reading-mult","errorCode":null,"errorMessage":"The single-split reader don't support reading multiple splits","messagePattern":"The single-split reader don't support reading multiple splits","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/AbstractSingleSplitReader.java","lineNumber":57,"sourceCode":"        }\n    }\n\n    public void internalPollNext(Collector<T> output) throws Exception {}\n\n    @Override\n    public final List<SingleSplit> snapshotState(long checkpointId) throws Exception {\n        return Collections.singletonList(new SingleSplit(snapshotStateToBytes(checkpointId)));\n    }\n\n    protected byte[] snapshotStateToBytes(long checkpointId) throws Exception {\n        // default nothing\n        return null;\n    }\n\n    @Override\n    public final void addSplits(List<SingleSplit> splits) {\n        if (splits.size() > 1) {\n            throw new UnsupportedOperationException(\n                    \"The single-split reader don't support reading multiple splits\");\n        }\n        byte[] restoredState = splits.get(0).getState();\n        if (restoredState != null && restoredState.length > 0) {\n            restoreState(restoredState);\n        }\n    }\n\n    protected void restoreState(byte[] restoredState) {\n        // default nothing\n    }\n\n    @Override\n    public final void handleNoMoreSplits() {\n        // nothing\n    }\n\n    @Override","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/AbstractSingleSplitReader.java#L39-L75","documentation":"AbstractSingleSplitReader.addSplits enforces that a single-split (non-parallel) source is only ever given exactly one split at restore time; more than one raises UnsupportedOperationException. The class is designed for sources that produce exactly one ReaderSplit, so restoring multiple splits is a programming/config error.","triggerScenarios":"Job restoration (addSplits called by the framework) delivering more than one SingleSplit to a reader extending AbstractSingleSplitReader — e.g. the split enumerator wrongly returned multiple splits for a source configured as single-split, or a saved checkpoint from a different parallelism is being restored.","commonSituations":"Changing source parallelism/dag-parsing so the enumerator emits several splits while the reader is still the single-split base class; mixing connector versions between a checkpoint and its restore; a custom Source whose SourceSplitEnumerator returns multiple splits but whose reader extends AbstractSingleSplitReader.","solutions":["Ensure the source's split enumerator returns exactly one split when the reader extends AbstractSingleSplitReader.","Restore the job with the same parallelism/settings it was checkpointed with, or start a fresh (non-restored) job.","If the source genuinely needs multiple splits, implement a parallel reader (SourceReader with normal split handling) instead of the single-split base.","Update all nodes to the same SeaTunnel/connector version so enumerator and reader behavior match."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before submitting/restoring, confirm the source yields a single split\nList<SingleSplit> splits = enumerator.enumerateSplits();\nif (splits.size() != 1) {\n    throw new IllegalStateException(\"single-split source must yield exactly 1 split, got \" + splits.size());\n}","typeGuard":null,"tryCatchPattern":"try {\n    reader.addSplits(splits);\n} catch (UnsupportedOperationException e) {\n    LOG.error(\"single-split reader got {} splits\", splits.size());\n    // fail the restore with a clear parallelism/config message\n    throw e;\n}","preventionTips":["Never change job parallelism between checkpoint and restore for single-split sources.","Keep enumerator and reader implementations consistent in custom sources.","Pin connector versions across the cluster so checkpoint restore uses matching code.","If you need parallelism, switch to a multi-split Source/Reader implementation."],"tags":["source","split","unsupported-operation","parallelism"],"backgroundTag":"unsupported-operation","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"}