{"record":{"id":"d993bf0e20a47f21","repo":"apache/seatunnel","slug":"read-split-s-error-due-to-s","errorCode":null,"errorMessage":"Read split %s error due to %s.","messagePattern":"Read split (.+?) error due to (.+?)\\.","errorType":"exception","errorClass":"org.apache.seatunnel.api.table.type.SeaTunnelException","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/IncrementalSourceScanFetcher.java","lineNumber":215,"sourceCode":"        normalizedRecords.addAll(taskContext.formatMessageTimestamp(outputBuffer.values()));\n        normalizedRecords.add(highWatermark);\n\n        final List<SourceRecords> sourceRecordsSet = new ArrayList<>();\n        sourceRecordsSet.add(new SourceRecords(normalizedRecords));\n        return sourceRecordsSet.iterator();\n    }\n\n    private void assertLowWatermark(SourceRecord lowWatermark) {\n        checkState(\n                isLowWatermarkEvent(lowWatermark),\n                String.format(\n                        \"The first record should be low watermark signal event, but actual is %s\",\n                        lowWatermark));\n    }\n\n    private void checkReadException() {\n        if (readException != null) {\n            throw new SeaTunnelException(\n                    String.format(\n                            \"Read split %s error due to %s.\",\n                            currentSnapshotSplit, readException.getMessage()),\n                    readException);\n        }\n    }\n\n    @Override\n    public void close() {\n        try {\n            // 1. try close the split task\n            if (snapshotSplitReadTask != null) {\n                try {\n                    snapshotSplitReadTask.shutdown();\n                } catch (Exception e) {\n                    log.error(\"Close snapshot split read task error\", e);\n                }\n            }","sourceCodeStart":197,"sourceCodeEnd":233,"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/IncrementalSourceScanFetcher.java#L197-L233","documentation":"IncrementalSourceScanFetcher runs snapshot scanning in a separate task thread; any exception thrown there is captured into readException. checkReadException(), invoked from pollSplitRecords/pollSplitRecordsIfExactlyOnce, rethrows it as SeaTunnelException wrapping the original cause, prefixed with the current snapshot split id. This converts an asynchronous reader failure into a synchronous failure visible at the poll site.","triggerScenarios":"The background scan task for a snapshot split fails (JDBC read error, binlog/LSN access error, deserialization failure, connection loss); the next call to pollSplitRecords detects the stored readException and rethrows it.","commonSituations":"Database connection dropped mid-scan; user lacks SELECT permission on part of the table; split range query fails due to schema change while the snapshot was running; network timeout between SeaTunnel worker and database.","solutions":["Inspect the cause (readException) via the SeaTunnelException's cause chain; it carries the real database/driver error.","Fix the underlying database issue: restore connectivity, grant SELECT on the captured table, or resolve the schema mismatch.","Enable checkpointing and restart the job so the snapshot split is re-scanned from its last restored position.","Increase connection/socket timeouts if the scan of very large tables routinely exceeds them."],"exampleFix":"// before: failing poll\nSourceRecords records = scanFetcher.pollSplitRecords();\n// after: catch and inspect root cause\ntry {\n    SourceRecords records = scanFetcher.pollSplitRecords();\n} catch (SeaTunnelException e) {\n    Throwable root = e.getCause(); // actual JDBC/driver error\n    throw new IOException(\"Snapshot split read failed: \" + root.getMessage(), root);\n}","handlingStrategy":"try-catch","validationCode":"// preflight: verify DB connectivity and SELECT privilege before job start\n// SELECT COUNT(*) FROM <captured-table> LIMIT 1;","typeGuard":null,"tryCatchPattern":"try {\n    records = scanFetcher.pollSplitRecords();\n} catch (SeaTunnelException e) {\n    Throwable cause = e.getCause();\n    log.error(\"Snapshot split read failed: {}\", cause, cause);\n    throw e;\n}","preventionTips":["Grant SELECT on all captured tables to the CDC user before starting.","Set generous JDBC connect/socket timeouts for large tables.","Avoid DDL changes during the snapshot phase."],"tags":["cdc","snapshot-scan","database","exception-wrapping"],"backgroundTag":"database-query-failed","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"}