{"record":{"id":"590c50c3216f2812","repo":"apache/seatunnel","slug":"splitfetcher-thread-d-received-unexpected-excepti","errorCode":null,"errorMessage":"SplitFetcher thread %d received unexpected exception while polling the records","messagePattern":"SplitFetcher thread (.+?) received unexpected exception while polling the records","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/reader/fetcher/SplitFetcher.java","lineNumber":164,"sourceCode":"\n            nextTask = getNextTaskUnsafe();\n            if (nextTask == null) {\n                // (spurious) wakeup, so just repeat\n                return true;\n            }\n\n            log.debug(\"Prepare to run {}\", nextTask);\n            // store task for #wakeUp\n            this.runningTask = nextTask;\n        } finally {\n            lock.unlock();\n        }\n\n        // execute the task outside of lock, so that it can be woken up\n        try {\n            nextTask.run();\n        } catch (Exception e) {\n            throw new RuntimeException(\n                    String.format(\n                            \"SplitFetcher thread %d received unexpected exception while polling the records\",\n                            fetcherId),\n                    e);\n        }\n\n        // re-acquire lock as all post-processing steps, need it\n        lock.lock();\n        try {\n            this.runningTask = null;\n        } finally {\n            lock.unlock();\n        }\n        return true;\n    }\n\n    private SplitFetcherTask getNextTaskUnsafe() {\n        if (!lock.isHeldByCurrentThread()) {","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/reader/fetcher/SplitFetcher.java#L146-L182","documentation":"SplitFetcher.runOnce() executes the current SplitFetcherTask outside the fetcher lock. Any unexpected Exception thrown by the task is wrapped in a RuntimeException carrying this formatted message including the fetcher thread id, then stored as an uncaught exception that later fails the source via checkErrors().","triggerScenarios":"nextTask.run() throws any RuntimeException/Error not already converted to IOException by FetchTask — e.g. deserialization errors, connector-specific runtime failures inside SplitReader.fetch(), or NullPointerExceptions in split handling.","commonSituations":"Malformed records causing serde exceptions; connector bug (NPE) in SplitReader; schema drift between source and expected SeaTunnelRow type; OOM-adjacent errors during record batching.","solutions":["Read the cause of this exception — it is always a wrap; the real failure is in the nested stack trace","Fix the underlying SplitReader exception identified by the cause (schema, serde, connection)","Upgrade/patch the connector if the cause indicates a library bug (NPE in fetch path)","Add validation of source records/schema before reading to catch serde issues early"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate splits/records before feeding fetcher\nsplits.forEach(s -> Objects.requireNonNull(s.splitId(), \"split must have id\"));","typeGuard":null,"tryCatchPattern":"try {\n    splitFetcherManager.checkErrors();\n} catch (RuntimeException e) {\n    Throwable cause = e.getCause(); // real failure from FetchTask/SplitReader\n    throw new SourceException(\"root fetch failure: \" + cause, cause);\n}","preventionTips":["Always read the cause chain — this message is only a wrapper","Null-check state used inside custom SplitReader.fetch() implementations","Test connectors with malformed data to catch serde NPEs before production","Keep SplitReader free of connector-specific unchecked throws where possible"],"tags":["fetcher","split-reader","runtime-exception","polling"],"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"}