{"record":{"id":"c5799212dc05dc48","repo":"apache/hadoop","slug":"rename-of-to-is-not-allowed-the-remote-loca","errorCode":null,"errorMessage":"Rename of {} to {} is not allowed. The remote location should be exactly one.","messagePattern":"Rename of (.+?) to (.+?) is not allowed\\. The remote location should be exactly one\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterFederationRename.java","lineNumber":105,"sourceCode":"   * Router federation rename across namespaces.\n   *\n   * @param src the source path. There is no mount point under the src path.\n   * @param dst the dst path.\n   * @param srcLocations the remote locations of src.\n   * @param dstLocations the remote locations of dst.\n   * @throws IOException if rename fails.\n   * @return true if rename succeeds.\n   */\n  public boolean routerFedRename(final String src, final String dst,\n      final List<RemoteLocation> srcLocations,\n      final List<RemoteLocation> dstLocations) throws IOException {\n    if (!rpcServer.isEnableRenameAcrossNamespace()) {\n      throw new IOException(\"Rename of \" + src + \" to \" + dst\n          + \" is not allowed, no eligible destination in the same namespace was\"\n          + \" found\");\n    }\n    if (srcLocations.size() != 1 || dstLocations.size() != 1) {\n      throw new IOException(\"Rename of \" + src + \" to \" + dst + \" is not\"\n          + \" allowed. The remote location should be exactly one.\");\n    }\n    RemoteLocation srcLoc = srcLocations.get(0);\n    RemoteLocation dstLoc = dstLocations.get(0);\n    checkSnapshotPath(srcLoc, dstLoc);\n    checkPermission(srcLoc, dstLoc);\n\n    UserGroupInformation routerUser = UserGroupInformation.getLoginUser();\n\n    try {\n      // as router user with saveJournal and task submission privileges\n      return routerUser.doAs((PrivilegedExceptionAction<Boolean>) () -> {\n        // Build and submit router federation rename job.\n        BalanceJob job = buildRouterRenameJob(srcLoc.getNameserviceId(),\n            dstLoc.getNameserviceId(), srcLoc.getDest(), dstLoc.getDest());\n        BalanceProcedureScheduler scheduler = rpcServer.getFedRenameScheduler();\n        countIncrement();\n        try {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterFederationRename.java#L87-L123","documentation":"Router federation rename requires exactly one remote location for each side of the rename, because it builds a single distcp job from one source nameservice to one destination nameservice. If the mount table yields multiple RemoteLocations for src or dst (multi-destination mount entries, e.g. HASH-based or ordered fallback lists), RouterFederationRename.routerFedRename throws this IOException.","triggerScenarios":"routerFedRename is invoked (cross-namespace rename enabled) and subclusterResolver.getLocationsForPath(src,dst) returns a list whose size != 1 for either side: the path maps to a mount entry with multiple destinations, or overlapping mount entries produce several locations.","commonSituations":"Mount table entries configured with multiple destination namespaces for load balancing/failover; nested mount entries where a parent and child entry both match; attempting fed rename on a path under a HASH-based multi-destination mount.","solutions":["Check the mount table: hdfs dfsrouteradmin -listMountTable, and find entries producing >1 location for the src/dst paths","Make the relevant mount entries single-destination (one -ns/-dst pair) or rename from a path that maps to exactly one namespace","Restructure nested mounts so only the most specific entry matches the paths involved in the rename"],"exampleFix":"# before: multi-destination mount produces several RemoteLocations\nhdfs dfsrouteradmin -add /data -ns ns0,ns1 -dst /data,\\/data -order HASH\n# after: single destination per mount\nhdfs dfsrouteradmin -rm /data\nhdfs dfsrouteradmin -add /data -ns ns0 -dst /data","handlingStrategy":"validation","validationCode":"// Reject paths that map to multiple destinations before calling rename\nList<RemoteLocation> srcLocs = resolver.getLocationsForPath(src, false);\nList<RemoteLocation> dstLocs = resolver.getLocationsForPath(dst, false);\nif (srcLocs.size() != 1 || dstLocs.size() != 1) {\n  throw new IllegalArgumentException(\n      \"Rename requires exactly one remote location per side; got src=\"\n      + srcLocs.size() + \" dst=\" + dstLocs.size());\n}","typeGuard":"boolean isSingleDestination(SubclusterResolver resolver, String path) throws IOException {\n  return resolver.getLocationsForPath(path, false).size() == 1;\n}","tryCatchPattern":"try {\n  boolean ok = dfs.rename(src, dst);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"remote location should be exactly one\")) {\n    // pick a path under a single-destination mount or reduce the mount entry's destinations\n  }\n  throw e;\n}","preventionTips":["Keep fed-rename candidate paths under single-destination mount entries","Avoid HASH/ordered multi-destination mounts on trees that rename operations target","Lint the mount table for multi-destination entries before enabling fed rename"],"tags":["hdfs","router","federation","rename","mount-table","multi-destination"],"backgroundTag":"ambiguous-mount-resolution","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}