{"record":{"id":"965d209b5dddaf63","repo":"apache/seatunnel","slug":"destination-path-s-already-exists","errorCode":null,"errorMessage":"Destination path %s already exists","messagePattern":"Destination path (.+?) already exists","errorType":"exception","errorClass":"FileAlreadyExistsException","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":842,"sourceCode":"     * @param src src\n     * @param dst dst\n     * @return result\n     * @throws IOException IOException\n     */\n    private boolean rename(FTPClient client, Path src, Path dst) throws IOException {\n        Path workDir = new Path(client.printWorkingDirectory());\n        Path absoluteSrc = makeAbsolute(workDir, src);\n        Path absoluteDst = makeAbsolute(workDir, dst);\n        if (!exists(client, absoluteSrc)) {\n            throw new FileNotFoundException(\"Source path \" + src + \" does not exist\");\n        }\n        if (isDirectory(absoluteDst)) {\n            // destination is a directory: rename goes underneath it with the\n            // source name\n            absoluteDst = new Path(absoluteDst, absoluteSrc.getName());\n        }\n        if (exists(client, absoluteDst)) {\n            throw new FileAlreadyExistsException(\"Destination path \" + dst + \" already exists\");\n        }\n        if (isParentOf(absoluteSrc, absoluteDst)) {\n            throw new IOException(\n                    \"Cannot rename \" + absoluteSrc + \" under itself\" + \" : \" + absoluteDst);\n        }\n        String from = absoluteSrc.toUri().getPath();\n        String to = absoluteDst.toUri().getPath();\n        return client.rename(from, to);\n    }\n\n    @Override\n    public Path getWorkingDirectory() {\n        // Return home directory always since we do not maintain state.\n        return getHomeDirectory();\n    }\n\n    @Override\n    public Path getHomeDirectory() {","sourceCodeStart":824,"sourceCodeEnd":860,"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#L824-L860","documentation":"rename() refuses to overwrite: after absolutizing paths (and resolving a directory destination by appending the source name), it checks the final destination via exists() and throws FileAlreadyExistsException 'Destination path %s already exists' when a file/dir is already there.","triggerScenarios":"rename(client, src, dst) called where exists(client, absoluteDst) is true after dst is normalized — including the case where dst is an existing directory and absoluteSrc.getName() already exists inside it.","commonSituations":"Re-running a job without cleanup so the previous run's output already sits at the destination; two concurrent jobs writing the same target file; sink save_mode set to something that doesn't pre-clean files; committing a temp file to a name that already exists.","solutions":["Delete or move the existing destination file before renaming (or have the job clean its output directory on start)","Configure schema_save_mode/data_save_mode (e.g. CREATE_SCHEMA_WHEN_NOT_EXIST with a unique output path per run)","Use unique destination names per execution (timestamp/partition suffix) to avoid collisions","Serialize job runs so two jobs don't target the same output file concurrently"],"exampleFix":"// before\nfs.rename(new Path(\"/tmp/part-0\"), new Path(\"/data/part-0\")); // may already exist\n// after\nPath dst = new Path(\"/data/part-0\");\nif (fs.exists(dst)) {\n    fs.delete(dst, false);\n}\nfs.rename(new Path(\"/tmp/part-0\"), dst);","handlingStrategy":"validation","validationCode":"// Java: delete-or-assert before rename\nPath dst = new Path(\"/data/part-0\");\nif (ftpFileSystem.exists(dst)) {\n    ftpFileSystem.delete(dst, false); // or fail fast\n}","typeGuard":null,"tryCatchPattern":"try {\n    fs.rename(src, dst);\n} catch (FileAlreadyExistsException e) {\n    logger.error(\"Destination exists: {} — clean up or use unique names\", dst);\n}","preventionTips":["Clean output directories at job start or use save_mode options that handle existing files","Generate unique destination names per run (timestamp/attempt suffix)","Prevent concurrent writes to the same destination path"],"tags":["ftp","file-already-exists","rename"],"backgroundTag":"file-already-exists","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"}