{"record":{"id":"28b3141e9f799025","repo":"apache/hadoop","slug":"cannot-rename-absolutesrc-under-itself-absolu","errorCode":null,"errorMessage":"Cannot rename {absoluteSrc} under itself : {absoluteDst}","messagePattern":"Cannot rename (.+?) under itself : (.+?)","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":691,"sourceCode":"    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\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.","sourceCodeStart":673,"sourceCodeEnd":709,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java#L673-L709","documentation":"rename() blocks moving a directory into its own subtree: after both paths are made absolute, isParentOf(absoluteSrc, absoluteDst) detects that dst lives under src and throws IOException(\"Cannot rename <src> under itself : <dst>\"). Such a move is logically self-contradictory, and FTP rename could not express it anyway.","triggerScenarios":"rename(\"/data\", \"/data/archive/data\") or any dst whose path has src as an ancestor; programmatic destination construction that nests the source inside itself (dst = src + \"/old\"); archive loops that build output paths under input paths.","commonSituations":"Archive/cleanup jobs deriving the destination from the source path (src + \"/archive\"); compaction flows moving a parent into a child; UI drag-and-drop letting users drop a folder into itself.","solutions":["Pick a destination outside the source subtree, e.g. a sibling directory (rename \"/data\" to \"/data-old\")","When nesting is required, copy-then-delete instead of rename: FileUtil.copy(fs, src, fs, dst, true, conf)","Guard path construction: reject any dst whose qualified path starts with the qualified src path + \"/\""],"exampleFix":"// before\nfs.rename(new Path(\"/data\"), new Path(\"/data/archive\"));  // IOException: under itself\n\n// after\nPath src = new Path(\"/data\");\nPath dst = new Path(\"/data-old\");            // sibling, not a child of src\nfs.rename(src, dst);","handlingStrategy":"validation","validationCode":"// reject destinations inside the source subtree before calling rename\nString s = src.makeQualified(fs).toUri().getPath();\nString d = dst.makeQualified(fs).toUri().getPath();\nif (d.startsWith(s.endsWith(\"/\") ? s : s + \"/\")) {\n  throw new IllegalArgumentException(\"dst is inside src: \" + d);\n}\nfs.rename(src, dst);","typeGuard":null,"tryCatchPattern":"catch IOException from rename, check message for \"under itself\", and re-run with a destination outside the subtree or fall back to copy+delete.","preventionTips":["Compose archive destinations as siblings, never children, of the source","Unit-test path-building helpers with src == dst-parent cases","For nesting moves, plan copy-then-delete from the start"],"tags":["ftp","hadoop","rename","path-validation"],"backgroundTag":"rename-into-itself","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}