{"record":{"id":"1343b02062ab0931","repo":"apache/hadoop","slug":"cannot-rename-symlink-to-its-target","errorCode":null,"errorMessage":"Cannot rename symlink {} to its target {}","messagePattern":"Cannot rename symlink (.+?) to its target (.+?)","errorType":"exception","errorClass":"FileAlreadyExistsException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirRenameOp.java","lineNumber":548,"sourceCode":"    } finally {\n      fsd.writeUnlock();\n    }\n    if (renameIIP != null) {\n      fsd.getEditLog().logRename(\n          srcIIP.getPath(), dstIIP.getPath(), mtime, logRetryCache);\n    }\n    // this rename never overwrites the dest so files deleted and collected\n    // are irrelevant.\n    return createRenameResult(fsd, renameIIP, false, null);\n  }\n\n  private static void validateDestination(\n      String src, String dst, INode srcInode)\n      throws IOException {\n    String error;\n    if (srcInode.isSymlink() &&\n        dst.equals(srcInode.asSymlink().getSymlinkString())) {\n      throw new FileAlreadyExistsException(\"Cannot rename symlink \" + src\n          + \" to its target \" + dst);\n    }\n    // dst cannot be a directory or a file under src\n    if (dst.startsWith(src)\n        && dst.charAt(src.length()) == Path.SEPARATOR_CHAR) {\n      error = \"Rename destination \" + dst\n          + \" is a directory or file under source \" + src;\n      NameNode.stateChangeLog.warn(\"DIR* FSDirectory.unprotectedRenameTo: \"\n          + error);\n      throw new IOException(error);\n    }\n\n    if (FSDirectory.isExactReservedName(src)\n        || FSDirectory.isExactReservedName(dst)) {\n      error = \"Cannot rename to or from /.reserved\";\n      throw new InvalidPathException(error);\n    }\n  }","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirRenameOp.java#L530-L566","documentation":"FileAlreadyExistsException thrown when renaming a symlink to the exact path the symlink points to. Such a rename would create a self-referential entry (the link resolving through itself), so validateDestination rejects it before any other destination check.","triggerScenarios":"`hdfs dfs -mv /link /target` where /link's stored target string is exactly /target; automation that 'normalizes' symlinks by moving them onto the files they reference; link-farm reorganization scripts.","commonSituations":"Symlinked warehouse layouts being flattened; tools that rename links assuming posix mv-into-directory semantics; snapshot copies where links and targets collide.","solutions":["Rename the link to a different path, or delete the link if only the target is wanted.","Guard in code: resolve the link target (getFileLinkStatus/getSymlink) and compare it with the destination before renaming."],"exampleFix":"// before\nfs.rename(linkPath, targetPath); // FileAlreadyExistsException: Cannot rename symlink to its target\n\n// after\nif (fs.getFileLinkStatus(linkPath).isSymlink()\n    && targetPath.makeQualified(fs.getUri(), fs.getWorkingDirectory()).equals(\n        fs.getLinkTarget(linkPath).makeQualified(fs.getUri(), linkPath.getParent()))) {\n  // refuse: would rename a symlink onto its own target\n} else {\n  fs.rename(linkPath, targetPath);\n}","handlingStrategy":"validation","validationCode":"if (fs.getFileLinkStatus(src).isSymlink()) {\n  Path target = fs.getLinkTarget(src).makeQualified(fs.getUri(), src.getParent());\n  Path qdst = dst.makeQualified(fs.getUri(), fs.getWorkingDirectory());\n  if (target.equals(qdst)) {\n    throw new FileAlreadyExistsException(\"Refusing to rename symlink onto its own target\");\n  }\n}\nfs.rename(src, dst);","typeGuard":null,"tryCatchPattern":"try {\n  fs.rename(src, dst);\n} catch (FileAlreadyExistsException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"to its target\")) {\n    // renaming a link onto its own target: pick another destination or delete the link\n  }\n  throw e;\n}","preventionTips":["Resolve link targets before renaming symlinks.","Skip symlinks in generic tree-move tools or handle them explicitly."],"tags":["hdfs","rename","symlink","file-already-exists"],"backgroundTag":"symlink-rename-conflict","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}