apache/seatunnel · error · FileNotFoundException

FTP directory does not exist: ${mask(absolute)}

Error message

FTP directory does not exist: ${mask(absolute)}

What it means

Thrown by SeaTunnelFTPFileSystem.list() as a FileNotFoundException when client.changeWorkingDirectory() fails for the requested directory, meaning the FTP server reports the directory does not exist (or is not accessible) at the given absolute path.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:532

        private static final int PAGE_SIZE = 1_000;
        private final FTPClient client;

        private FtpListingSession(FTPClient client) {
            this.client = client;
        }

        @Override
        public FileStatus getFileStatus(Path path) throws IOException {
            return SeaTunnelFTPFileSystem.this.getFileStatus(client, path);
        }

        @Override
        public void list(Path directory, FileStatusConsumer consumer) throws IOException {
            Path workDir = new Path(client.printWorkingDirectory());
            Path absolute = makeAbsolute(workDir, directory);
            String previousDirectory = client.printWorkingDirectory();
            if (!client.changeWorkingDirectory(absolute.toUri().getPath())) {
                throw new FileNotFoundException("FTP directory does not exist: " + mask(absolute));
            }
            Throwable failure = null;
            try {
                FTPListParseEngine engine = client.initiateListParsing();
                if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                    throw new IOException(
                            "FTP LIST failed for path="
                                    + mask(absolute)
                                    + ", replyCode="
                                    + client.getReplyCode());
                }
                while (engine.hasNext()) {
                    FTPFile[] files = engine.getNext(PAGE_SIZE);
                    int skipped = emitFileStatuses(files, absolute, consumer);
                    if (skipped > 0) {
                        LOG.warn(
                                "Skipped "
                                        + skipped

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify the exact directory path exists with an FTP client (ls/cwd) using the same credentials
  2. Check path case sensitivity and leading/trailing slashes in the connector config
  3. Ensure the FTP user's home/permission allows entering the directory
  4. Pre-check with fs.exists(dir) before listing
  5. If the path can legitimately disappear, catch FileNotFoundException and treat as empty

Example fix

// before
FileStatus[] files = fs.listStatus(new Path("/remote/Data"));
// after
Path dir = new Path("/remote/data"); // match server case exactly
if (fs.exists(dir)) {
    FileStatus[] files = fs.listStatus(dir);
}
Defensive patterns

Strategy: try-catch

Validate before calling

Path dir = new Path("/remote/data");
if (!fs.exists(dir)) {
    throw new IllegalArgumentException("FTP directory missing: " + dir);
}

Try / catch

try {
    FileStatus[] files = fs.listStatus(dir);
} catch (FileNotFoundException e) {
    if (e.getMessage().contains("FTP directory does not exist")) {
        // handle missing dir as empty input or fail with a clear config error
    } else { throw e; }
}

Prevention

When it happens

Trigger: Listing a directory whose path does not exist on the FTP server; path typo or wrong relative path resolved against the FTP working directory; the directory was deleted between the existence check and the list; user lacks permission to enter the directory (CWD rejected).

Common situations: SeaTunnel FTP source configured with a remote path that does not exist; case-sensitivity mismatch (Linux FTP servers are case-sensitive); path containing a symlink or mount not present on the server; credentials scoped to a different home directory than expected.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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