{"record":{"id":"ec4922bb0a558d2f","repo":"apache/seatunnel","slug":"file-split-fail-ec4922","errorCode":"FILE_SPLIT_FAIL","errorMessage":"Split parquet file for [%s] failed, cause=%s: %s","messagePattern":"Split parquet file for \\[(.+?)\\] failed, cause=(.+?): (.+?)","errorType":"error_code","errorClass":"SeaTunnelRuntimeException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/source/split/ParquetFileSplitStrategy.java","lineNumber":86,"sourceCode":"\n    public ParquetFileSplitStrategy(long splitSizeBytes, HadoopConf hadoopConf) {\n        if (splitSizeBytes <= 0) {\n            throw new SeaTunnelRuntimeException(\n                    FileConnectorErrorCode.FILE_SPLIT_SIZE_ILLEGAL,\n                    String.format(\n                            \"file_split_size must be greater than 0 when enable_file_split=true, but got: %d\",\n                            splitSizeBytes));\n        }\n        this.splitSizeBytes = splitSizeBytes;\n        this.hadoopFileSystemProxy = new HadoopFileSystemProxy(hadoopConf);\n    }\n\n    @Override\n    public List<FileSourceSplit> split(String tableId, String filePath) {\n        try {\n            return splitByRowGroups(tableId, filePath, readRowGroups(filePath));\n        } catch (IOException e) {\n            throw new SeaTunnelRuntimeException(\n                    FileConnectorErrorCode.FILE_SPLIT_FAIL,\n                    String.format(\n                            \"Split parquet file for [%s] failed, cause=%s: %s\",\n                            filePath, e.getClass().getSimpleName(), e.getMessage()),\n                    e);\n        }\n    }\n\n    /**\n     * Core split logic based on row group metadata. This method is IO-free and unit-test friendly.\n     */\n    List<FileSourceSplit> splitByRowGroups(\n            String tableId, String filePath, List<BlockMetaData> rowGroups) {\n        List<FileSourceSplit> splits = new ArrayList<>();\n        if (rowGroups == null || rowGroups.isEmpty()) {\n            return splits;\n        }\n        long currentStart = 0;","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/source/split/ParquetFileSplitStrategy.java#L68-L104","documentation":"Parquet file splitting failed in ParquetFileSplitStrategy. The strategy reads the Parquet footer to enumerate row groups and turn them into FileSourceSplits; any IOException during that I/O (unreadable file, corrupt footer, network filesystem hiccup) is wrapped in SeaTunnelRuntimeException with code FILE_SPLIT_FAIL. The original exception class and message are preserved in the message.","triggerScenarios":"Calling split(tableId, filePath) when readRowGroups(filePath) throws IOException: the file does not exist or is inaccessible, the path is a directory, the file is not valid Parquet (missing/corrupt footer), or reading from remote storage (HDFS/S3) fails mid-read.","commonSituations":"Configured path typo or bucket/permission mistake; file truncated or still being written by an upstream job; non-Parquet file with .parquet extension; Hadoop/Parquet version incompatibility corrupting footer parsing; transient S3/HDFS connectivity failures.","solutions":["Check the 'cause=...' part of the message and the wrapped exception to see the root IOException; fix that issue first","Verify the path exists, is a readable file, and is a valid Parquet file (e.g. open it with parquet-tools / pyarrow)","Confirm the filesystem/credentials config (HDFS namenode, S3 endpoint/AK/SK) is correct","If the file is still being written, exclude it or wait for the writer to complete before running the job","Re-run the job if the cause was a transient network failure"],"exampleFix":"// before\nString path = \"/data/export/events\"; // missing .parquet, actually a directory\n// after\nString path = \"/data/export/events.parquet\"; // verified: exists, readable, valid parquet","handlingStrategy":"validation","validationCode":"// Java (Hadoop FileSystem available)\nFileSystem fs = new Path(filePath).getFileSystem(conf);\nif (!fs.exists(new Path(filePath))) throw new IllegalArgumentException(\"missing file: \" + filePath);\nFileStatus st = fs.getFileStatus(new Path(filePath));\nif (st.isDirectory()) throw new IllegalArgumentException(\"not a file: \" + filePath);\nif (st.getLen() < 8) throw new IllegalArgumentException(\"too small to be parquet: \" + filePath);","typeGuard":null,"tryCatchPattern":"try {\n    strategy.split(tableId, filePath);\n} catch (SeaTunnelRuntimeException e) {\n    if (FileConnectorErrorCode.FILE_SPLIT_FAIL.equals(e.getErrorCode())) {\n        LOG.warn(\"Skipping unreadable parquet file {}: {}\", filePath, e.getCause());\n    } else { throw e; }\n}","preventionTips":["Always verify the path exists, is a file, and is readable before splitting","Validate Parquet footers upstream (e.g. parquet-tools) before ingesting","Exclude files still being written (use a staging/complete marker convention)","Check the 'cause=' section of the message to fix the root IOException"],"tags":["io","parquet","file-split","source"],"backgroundTag":"file-read-failed","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"}