apache/seatunnel · error · IOException

SftpException wrapped (pwd failed while renaming)

Error message

SftpException wrapped (pwd failed while renaming)

What it means

rename() resolves the working directory via channel.pwd() before making src/dst absolute; if pwd throws, the SftpException is wrapped in an IOException. This happens before any existence checks, so it indicates the channel/server was already in a bad state when the rename started.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java:439

        }
        ArrayList<FileStatus> fileStats = new ArrayList<FileStatus>();
        for (int i = 0; i < sftpFiles.size(); i++) {
            LsEntry entry = sftpFiles.get(i);
            String fname = entry.getFilename();
            // skip current and parent directory, ie. "." and ".."
            if (!".".equalsIgnoreCase(fname) && !"..".equalsIgnoreCase(fname)) {
                fileStats.add(getFileStatus(client, entry, absolute));
            }
        }
        return fileStats.toArray(new FileStatus[fileStats.size()]);
    }

    private boolean rename(ChannelSftp channel, Path src, Path dst) throws IOException {
        Path workDir;
        try {
            workDir = new Path(channel.pwd());
        } catch (SftpException e) {
            throw new IOException(e);
        }
        Path absoluteSrc = makeAbsolute(workDir, src);
        Path absoluteDst = makeAbsolute(workDir, dst);

        if (!exists(channel, absoluteSrc)) {
            throw new IOException(String.format(E_SPATH_NOTEXIST, src));
        }
        if (exists(channel, absoluteDst)) {
            throw new IOException(String.format(E_DPATH_EXIST, dst));
        }
        boolean renamed = true;
        try {
            final String previousCwd = channel.pwd();
            channel.cd("/");
            channel.rename(src.toUri().getPath(), dst.toUri().getPath());
            channel.cd(previousCwd);
        } catch (SftpException e) {
            renamed = false;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Reconnect and retry the rename
  2. Enable SSH keep-alive (ServerAliveInterval) to keep the session alive across job phases
  3. Check the wrapped SftpException id to diagnose server vs transport failure
  4. Ensure channels are returned to the pool and revalidated before reuse
Defensive patterns

Strategy: retry

Validate before calling

try {
    fs.exists(new Path("/")); // channel health probe
} catch (IOException e) {
    reconnect();
}

Try / catch

try {
    fs.rename(src, dst);
} catch (IOException e) {
    if (e.getCause() instanceof SftpException) { reconnect(); /* retry rename */ }
    throw e;
}

Prevention

When it happens

Trigger: fs.rename(src, dst) (commit phase, file-move steps) when the SFTP session is closed, authentication expired, or the server fails the pwd request.

Common situations: Session idle timeout before the job's commit/rename step; server restart between write and rename; stale pooled channel; firewall dropping long-lived SSH control connection.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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