{"record":{"id":"84f580fa75809498","repo":"apache/hadoop","slug":"cannot-rename-source-absolutesrc-to-absoluteds","errorCode":null,"errorMessage":"Cannot rename source: {absoluteSrc} to {absoluteDst} -only same directory renames are supported","messagePattern":"Cannot rename source: (.+?) to (.+?) -only same directory renames are supported","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java","lineNumber":696,"sourceCode":"    }\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\n          + \" already exists\");\n    }\n    URI parentSrc = absoluteSrc.getParent().toUri();\n    URI parentDst = absoluteDst.getParent().toUri();\n    if (isParentOf(absoluteSrc, absoluteDst)) {\n      throw new IOException(\"Cannot rename \" + absoluteSrc + \" under itself\"\n      + \" : \"+ absoluteDst);\n    }\n\n    if (!parentSrc.toString().equals(parentDst.toString())) {\n      throw new IOException(\"Cannot rename source: \" + absoluteSrc\n          + \" to \" + absoluteDst\n          + \" -\"+ E_SAME_DIRECTORY_ONLY);\n    }\n    String from = absoluteSrc.getName();\n    String to = absoluteDst.getName();\n    client.changeWorkingDirectory(parentSrc.getPath());\n    boolean renamed = client.rename(from, to);\n    return renamed;\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":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java#L678-L714","documentation":"FTP's RNFR/RNTO can only rename an entry within its parent directory. FTPFileSystem enforces this: if the parent directories of the absolute source and destination differ (compared as parent URIs), it throws IOException(\"Cannot rename source ... - only same directory renames are supported\") without contacting the server.","triggerScenarios":"rename(\"/dir1/file\", \"/dir2/file\") or any dst whose parent differs from src's parent, including \"move into another directory\" intentions; also URI normalization differences (trailing slash, encoding) making equal parents compare unequal as strings.","commonSituations":"Porting code from LocalFileSystem/HDFS where cross-directory rename works; ingest flows trying to \"move\" files between FTP directories over an ftp:// URL; path strings assembled with inconsistent encoding or slashes so the parent string comparison fails even in the same directory.","solutions":["Implement move as copy + delete: FileUtil.copy(fs, src, fs, dst, true, conf)","If you only mean to rename, keep both paths inside the same parent directory","Normalize both parents (makeQualified + getParent().toUri()) before assuming they are equal or different","Stage data on HDFS/local when frequent moves are needed; treat FTP purely as a transfer source/sink"],"exampleFix":"// before\nfs.rename(new Path(\"/incoming/f.dat\"), new Path(\"/archive/f.dat\"));  // same-dir only -> IOException\n\n// after\nboolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);\nif (!moved) {\n  throw new IOException(\"copy-move failed: \" + src + \" -> \" + dst);\n}","handlingStrategy":"validation","validationCode":"// only same-parent renames are supported on ftp://\nif (!src.getParent().equals(dst.getParent())) {\n  boolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);\n  if (!moved) { throw new IOException(\"copy-move failed: \" + src); }\n} else {\n  fs.rename(src, dst);\n}","typeGuard":null,"tryCatchPattern":"catch IOException containing \"only same directory renames are supported\" and fall back to FileUtil.copy with deleteSource=true.","preventionTips":["Treat ftp:// rename as rename-in-place only; use copy+delete for moves","Normalize both parents before comparing (encoding, trailing slashes)","Stage files on HDFS/local when the workflow needs frequent moves"],"tags":["ftp","hadoop","rename","unsupported-operation"],"backgroundTag":"cross-directory-rename-unsupported","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}