apache/seatunnel · error · IOException

SftpException wrapped (pwd failed while listing status)

Error message

SftpException wrapped (pwd failed while listing status)

What it means

listStatus() starts by resolving the remote working directory with client.pwd(); a failing pwd is rethrown as a bare IOException wrapping the SftpException. The list operation never reached the actual directory read — the channel was already unusable or the server rejected the pwd request.

Source

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

            } catch (SftpException e) {
                status = false;
            }
            return status;
        }
    }

    /**
     * Convenience method, so that we don't open a new connection when using this method from within
     * another method. Otherwise every API invocation incurs the overhead of opening/closing a TCP
     * connection.
     */
    @SuppressWarnings("unchecked")
    private FileStatus[] listStatus(ChannelSftp client, Path file) throws IOException {
        Path workDir;
        try {
            workDir = new Path(client.pwd());
        } catch (SftpException e) {
            throw new IOException(e);
        }
        Path absolute = makeAbsolute(workDir, file);
        FileStatus fileStat = getFileStatus(client, absolute);
        if (!fileStat.isDirectory()) {
            return new FileStatus[] {fileStat};
        }
        Vector<LsEntry> sftpFiles;
        try {
            sftpFiles = (Vector<LsEntry>) client.ls(absolute.toUri().getPath());
        } catch (SftpException e) {
            throw new IOException(e);
        }
        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)) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Re-establish the SFTP connection (connect()) and retry the list
  2. Add SSH keep-alive to prevent idle channel death
  3. Verify credentials/session validity before long operations
  4. Check the wrapped SftpException id to determine server-side vs transport failure
Defensive patterns

Strategy: retry

Validate before calling

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

Try / catch

try {
    FileStatus[] st = fs.listStatus(path);
} catch (IOException e) {
    if (e.getCause() instanceof SftpException) { reconnect(); /* retry once */ }
    throw e;
}

Prevention

When it happens

Trigger: Any call that lists status (listStatus, and indirectly getFileStatus/exists/delete paths that call it) when the SFTP channel is disconnected, unauthenticated, or the server errors on pwd.

Common situations: Long-running jobs whose SFTP sessions timed out; connection pool handing out stale channels; network/NAT drop; server restarted between connect and list.

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/7a204e0704eaa318. Report an issue: GitHub.