apache/seatunnel · error · ClickhouseConnectorException

sourcePath is null

Error message

sourcePath is null

What it means

ScpFileTransfer.transferAndChown(List<String> sourcePaths, String targetPath) validates its input and throws ILLEGAL_ARGUMENT when the sourcePaths list is null. This is a fail-fast argument check before delegating each path to the single-path transfer.

Source

Thrown at seatunnel-connectors-v2/connector-clickhouse/src/main/java/org/apache/seatunnel/connectors/seatunnel/clickhouse/sink/file/ScpFileTransfer.java:129

        command.add("ls");
        command.add("-l");
        command.add(
                targetPath.substring(0, StringUtils.stripEnd(targetPath, "/").lastIndexOf("/"))
                        + "/");
        command.add("| tail -n 1 | awk '{print $3}' | xargs -t -i chown -R {}:{} " + targetPath);
        try {
            String finalCommand = String.join(" ", command);
            log.info("execute remote command: " + finalCommand);
            clientSession.executeRemoteCommand(finalCommand);
        } catch (IOException e) {
            // always return error cause xargs return shell command result
        }
    }

    @Override
    public void transferAndChown(List<String> sourcePaths, String targetPath) {
        if (sourcePaths == null) {
            throw new ClickhouseConnectorException(
                    CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT, "sourcePath is null");
        }
        sourcePaths.forEach(sourcePath -> transferAndChown(sourcePath, targetPath));
    }

    @Override
    public void close() {
        if (clientSession != null && clientSession.isOpen()) {
            try {
                clientSession.close();
            } catch (IOException e) {
                throw new ClickhouseConnectorException(
                        ClickhouseConnectorErrorCode.SSH_OPERATION_FAILED,
                        "Failed to close ssh session",
                        e);
            }
        }
        if (sshClient != null && sshClient.isOpen()) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Ensure the caller initializes the source file list before invoking transferAndChown
  2. Pass an empty list instead of null if there are legitimately no files to transfer
  3. Trace where the list is produced and fix the code path that leaves it null

Example fix

// before
List<String> sourcePaths = null;
transfer.transferAndChown(sourcePaths, targetPath);
// after
List<String> sourcePaths = collectedFiles != null ? collectedFiles : Collections.emptyList();
transfer.transferAndChown(sourcePaths, targetPath);
Defensive patterns

Strategy: type-guard

Validate before calling

if (sourcePaths == null) {
    throw new IllegalArgumentException("sourcePaths must not be null; pass an empty list instead");
}

Type guard

boolean hasValidSourcePaths = (sourcePaths != null);

Try / catch

try {
    transfer.transferAndChown(sourcePaths, targetPath);
} catch (ClickhouseConnectorException e) {
    if ("sourcePath is null".equals(e.getMessage())) {
        log.error("File list was null; check upstream collection step");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling transferAndChown with a null List argument — e.g. upstream code that built the file list conditionally and never assigned it, or a config that produced no files and the list was left null instead of empty.

Common situations: Programmatic use of the ClickHouse sink's file transfer API where the local temp-file collection step failed silently and returned null instead of an empty list.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/f1bbd6fcf2ed99fd. Report an issue: GitHub.