{"record":{"id":"c2200aa087119c82","repo":"apache/seatunnel","slug":"sourcepath-is-null","errorCode":null,"errorMessage":"sourcePath is null","messagePattern":"sourcePath is null","errorType":"validation","errorClass":"ClickhouseConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-clickhouse/src/main/java/org/apache/seatunnel/connectors/seatunnel/clickhouse/sink/file/RsyncFileTransfer.java","lineNumber":168,"sourceCode":"        command.add(\"ls\");\n        command.add(\"-l\");\n        command.add(\n                targetPath.substring(0, StringUtils.stripEnd(targetPath, \"/\").lastIndexOf(\"/\"))\n                        + \"/\");\n        command.add(\"| tail -n 1 | awk '{print $3}' | xargs -t -i chown -R {}:{} \" + targetPath);\n        try {\n            String finalCommand = String.join(\" \", command);\n            log.info(\"execute remote command: \" + finalCommand);\n            clientSession.executeRemoteCommand(finalCommand);\n        } catch (IOException e) {\n            // always return error cause xargs return shell command result\n        }\n    }\n\n    @Override\n    public void transferAndChown(List<String> sourcePaths, String targetPath) {\n        if (sourcePaths == null) {\n            throw new ClickhouseConnectorException(\n                    CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT, \"sourcePath is null\");\n        }\n        sourcePaths.forEach(sourcePath -> transferAndChown(sourcePath, targetPath));\n    }\n\n    @Override\n    public void close() {\n        if (clientSession != null && clientSession.isOpen()) {\n            try {\n                clientSession.close();\n            } catch (IOException e) {\n                throw new ClickhouseConnectorException(\n                        ClickhouseConnectorErrorCode.SSH_OPERATION_FAILED,\n                        \"Failed to close ssh session\",\n                        e);\n            }\n        }\n        if (sshClient != null && sshClient.isOpen()) {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-clickhouse/src/main/java/org/apache/seatunnel/connectors/seatunnel/clickhouse/sink/file/RsyncFileTransfer.java#L150-L186","documentation":"RsyncFileTransfer.transferAndChown(List<String>, String) rejects a null source path list with ILLEGAL_ARGUMENT / \"sourcePath is null\" before iterating; each non-null entry is then transferred and ownership-changed via the single-path overload.","triggerScenarios":"Calling transferAndChown with a null List<String> of source paths — e.g. an upstream flush step passing null after file generation failed instead of skipping the transfer.","commonSituations":"Programmatic use of the file transfer API where the caller builds the path list from an operation that returned null; a failed prepareCommit still invoking transfer with an uninitialized list.","solutions":["Ensure the caller passes a non-null list; skip the transfer when no files were generated (use an empty list instead of null)","Initialize the source path list at declaration so it can never be null","Guard call sites: only invoke transferAndChown when generated file collection succeeded"],"exampleFix":"// before\ntransfer.transferAndChown(clickhouseLocalFiles, targetPath); // may be null\n// after\nif (clickhouseLocalFiles != null && !clickhouseLocalFiles.isEmpty()) {\n    transfer.transferAndChown(clickhouseLocalFiles, targetPath);\n}","handlingStrategy":"type-guard","validationCode":"if (sourcePaths == null || sourcePaths.isEmpty()) return; // skip transfer","typeGuard":"if (sourcePaths == null || sourcePaths.stream().anyMatch(Objects::isNull)) {\n    throw new IllegalArgumentException(\"sourcePaths must be a non-null list of non-null paths\");\n}","tryCatchPattern":null,"preventionTips":["Initialize file-path lists at declaration, never leave them null","Skip transfer when no files were generated instead of passing null","Assert non-null arguments at call sites before invoking transfer APIs"],"tags":["null-check","argument-validation","clickhouse"],"backgroundTag":"null-argument","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"}