{"record":{"id":"7747d8cb0972c335","repo":"apache/seatunnel","slug":"ftp-directory-does-not-exist-mask-absolute","errorCode":null,"errorMessage":"FTP directory does not exist: ${mask(absolute)}","messagePattern":"FTP directory does not exist: (.+?)","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java","lineNumber":532,"sourceCode":"        private static final int PAGE_SIZE = 1_000;\n        private final FTPClient client;\n\n        private FtpListingSession(FTPClient client) {\n            this.client = client;\n        }\n\n        @Override\n        public FileStatus getFileStatus(Path path) throws IOException {\n            return SeaTunnelFTPFileSystem.this.getFileStatus(client, path);\n        }\n\n        @Override\n        public void list(Path directory, FileStatusConsumer consumer) throws IOException {\n            Path workDir = new Path(client.printWorkingDirectory());\n            Path absolute = makeAbsolute(workDir, directory);\n            String previousDirectory = client.printWorkingDirectory();\n            if (!client.changeWorkingDirectory(absolute.toUri().getPath())) {\n                throw new FileNotFoundException(\"FTP directory does not exist: \" + mask(absolute));\n            }\n            Throwable failure = null;\n            try {\n                FTPListParseEngine engine = client.initiateListParsing();\n                if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {\n                    throw new IOException(\n                            \"FTP LIST failed for path=\"\n                                    + mask(absolute)\n                                    + \", replyCode=\"\n                                    + client.getReplyCode());\n                }\n                while (engine.hasNext()) {\n                    FTPFile[] files = engine.getNext(PAGE_SIZE);\n                    int skipped = emitFileStatuses(files, absolute, consumer);\n                    if (skipped > 0) {\n                        LOG.warn(\n                                \"Skipped \"\n                                        + skipped","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java#L514-L550","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the exact directory path exists with an FTP client (ls/cwd) using the same credentials","Check path case sensitivity and leading/trailing slashes in the connector config","Ensure the FTP user's home/permission allows entering the directory","Pre-check with fs.exists(dir) before listing","If the path can legitimately disappear, catch FileNotFoundException and treat as empty"],"exampleFix":"// before\nFileStatus[] files = fs.listStatus(new Path(\"/remote/Data\"));\n// after\nPath dir = new Path(\"/remote/data\"); // match server case exactly\nif (fs.exists(dir)) {\n    FileStatus[] files = fs.listStatus(dir);\n}","handlingStrategy":"try-catch","validationCode":"Path dir = new Path(\"/remote/data\");\nif (!fs.exists(dir)) {\n    throw new IllegalArgumentException(\"FTP directory missing: \" + dir);\n}","typeGuard":null,"tryCatchPattern":"try {\n    FileStatus[] files = fs.listStatus(dir);\n} catch (FileNotFoundException e) {\n    if (e.getMessage().contains(\"FTP directory does not exist\")) {\n        // handle missing dir as empty input or fail with a clear config error\n    } else { throw e; }\n}","preventionTips":["Verify directory paths (exact case, slashes) with an FTP client using the same credentials","Pre-check fs.exists() before listing","Remember FTP servers are case-sensitive and user home dirs change path resolution","Catch FileNotFoundException where an absent directory is an acceptable input state"],"tags":["ftp","directory-not-found","list","path"],"backgroundTag":"file-not-found","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"}