{"record":{"id":"cf05c45e4a9c02b7","repo":"apache/seatunnel","slug":"illegal-argument-cf05c4","errorCode":"ILLEGAL_ARGUMENT","errorMessage":"Binary sink custom_filename only supports a single source file in each sink task. Existing source file: \" + existingRelativePath + \", new source file: \" + relativePath","messagePattern":"Binary sink custom_filename only supports a single source file in each sink task\\. Existing source file: \" \\+ existingRelativePath \\+ \", new source file: \" \\+ relativePath","errorType":"error_code","errorClass":"FileConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sink/writer/BinaryWriteStrategy.java","lineNumber":111,"sourceCode":"        String beingWrittenFilePath = beingWrittenFile.get(relativePath);\n        if (beingWrittenFilePath != null) {\n            return beingWrittenFilePath;\n        } else {\n            String[] pathSegments = new String[] {transactionDirectory, relativePath};\n            String newBeingWrittenFilePath = String.join(File.separator, pathSegments);\n            beingWrittenFile.put(relativePath, newBeingWrittenFilePath);\n            return newBeingWrittenFilePath;\n        }\n    }\n\n    private String getOrCreateCustomFilePathBeingWritten(String relativePath) {\n        String beingWrittenFilePath = beingWrittenFile.get(relativePath);\n        if (beingWrittenFilePath != null) {\n            return beingWrittenFilePath;\n        } else {\n            if (!beingWrittenFile.isEmpty()) {\n                String existingRelativePath = beingWrittenFile.keySet().iterator().next();\n                throw new FileConnectorException(\n                        CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT,\n                        \"Binary sink custom_filename only supports a single source file in each \"\n                                + \"sink task. Existing source file: \"\n                                + existingRelativePath\n                                + \", new source file: \"\n                                + relativePath);\n            }\n            String[] pathSegments =\n                    new String[] {\n                        transactionDirectory,\n                        FileBaseSinkOptions.NON_PARTITION,\n                        generateFileName(transactionId)\n                    };\n            String newBeingWrittenFilePath = String.join(File.separator, pathSegments);\n            beingWrittenFile.put(relativePath, newBeingWrittenFilePath);\n            return newBeingWrittenFilePath;\n        }\n    }","sourceCodeStart":93,"sourceCodeEnd":129,"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/sink/writer/BinaryWriteStrategy.java#L93-L129","documentation":"With custom_filename enabled in a binary sink, each sink task may write at most one source file: the strategy keeps a map from source relativePath to output path, and if a second, different source relativePath arrives while another is already being written it throws ILLEGAL_ARGUMENT. Custom file naming requires a 1:1 mapping between source file and sink task.","triggerScenarios":"getOrCreateCustomFilePathBeingWritten (called via getOrCreateFilePathBeingWritten) receives a new relativePath while beingWrittenFile already holds a different, non-empty entry — e.g. one sink task assigned multiple source files.","commonSituations":"custom_filename = true with source parallelism/splits causing multiple source files to land in the same sink task; small source files merged so one reader task covers several files.","solutions":["Set custom_filename = false to let the sink generate per-output names automatically","Increase sink parallelism so each task handles a single source file, or configure source splits so one file maps to one task","Remove the merge/small-file compaction option on the source so tasks are not assigned multiple files"],"exampleFix":"// before\nsink {\n  LocalFile {\n    file_format_type = \"binary\"\n    custom_filename = true\n  }\n}\n// after\nsink {\n  LocalFile {\n    file_format_type = \"binary\"\n    custom_filename = false\n  }\n}","handlingStrategy":"validation","validationCode":"// before enabling custom_filename on a binary sink\nif (sinkConfig.customFilename && expectedSourceFilesPerTask > 1) {\n  throw new IllegalArgumentException(\"custom_filename=true requires exactly one source file per sink task\");\n}","typeGuard":null,"tryCatchPattern":"try { strategy.getOrCreateCustomFilePathBeingWritten(relativePath); } catch (FileConnectorException e) {\n  if (CommonErrorCode.ILLEGAL_ARGUMENT.equals(e.getErrorCode())) {\n    /* disable custom_filename or re-shard source files one-per-task */\n  }\n}","preventionTips":["Only enable custom_filename when source splitting guarantees one file per reader task","Avoid source-side file merging/compaction with custom_filename=true","Match sink parallelism to the number of source files"],"tags":["file-sink","binary","custom-filename","parallelism"],"backgroundTag":"invalid-argument-value","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"}