{"record":{"id":"1e1ad4e0e788feca","repo":"apache/hadoop","slug":"rename-of-to-is-not-allowed-the-number-of-r","errorCode":null,"errorMessage":"Rename of {} to {} is not allowed. The number of remote locations for both source and target should be same.","messagePattern":"Rename of (.+?) to (.+?) is not allowed\\. The number of remote locations for both source and target should be same\\.","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/RouterClientProtocol.java","lineNumber":638,"sourceCode":"      throws IOException {\n    rpcServer.checkOperation(NameNode.OperationCategory.WRITE);\n\n    final List<RemoteLocation> srcLocations =\n        rpcServer.getLocationsForPath(src, true, false);\n    final List<RemoteLocation> dstLocations =\n        rpcServer.getLocationsForPath(dst, false, false);\n    // srcLocations may be trimmed by getRenameDestinations()\n    final List<RemoteLocation> locs = new LinkedList<>(srcLocations);\n    RemoteParam dstParam = getRenameDestinations(locs, dstLocations);\n    if (locs.isEmpty()) {\n      return rbfRename.routerFedRename(src, dst, srcLocations, dstLocations);\n    }\n    RemoteMethod method = new RemoteMethod(\"rename\",\n        new Class<?>[] {String.class, String.class},\n        new RemoteParam(), dstParam);\n    if (isMultiDestDirectory(src)) {\n      if (locs.size() != srcLocations.size()) {\n        throw new IOException(\"Rename of \" + src + \" to \" + dst + \" is not\"\n            + \" allowed. The number of remote locations for both source and\"\n            + \" target should be same.\");\n      }\n      return rpcClient.invokeAll(locs, method);\n    } else {\n      return rpcClient.invokeSequential(locs, method, Boolean.class,\n          Boolean.TRUE);\n    }\n  }\n\n  @Override\n  public void rename2(final String src, final String dst,\n      final Options.Rename... options) throws IOException {\n    rpcServer.checkOperation(NameNode.OperationCategory.WRITE);\n\n    final List<RemoteLocation> srcLocations =\n        rpcServer.getLocationsForPath(src, true, false);\n    final List<RemoteLocation> dstLocations =","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java#L620-L656","documentation":"In RouterClientProtocol.rename(), for a multi-destination directory (isMultiDestDirectory(src) true), the Router proxies rename to every remote location in parallel. getRenameDestinations() may trim locations whose destination-side mapping is absent; if the remaining list size differs from srcLocations.size(), the source/target location counts no longer line up and the Router aborts with IOException rather than partially renaming only some namespaces.","triggerScenarios":"rename()/rename2 via Router where src is a mount with multiple destinations and the dst mount has a different number of destinations or non-matching orderings (e.g. src mounted in ns0+ns1, dst mounted only in ns0, or dst default location ordering differs); getRenameDestinations drops a location because dst cannot resolve in that nameservice.","commonSituations":"Asymmetric mount tables (one side of the rename has 2 locations, the other 1); renaming between a multi-destination mount and a single-destination mount; mount tables edited concurrently so src and dst snapshots disagree.","solutions":["Align the destination counts: give dst the same set of nameservice destinations as src (update the mount entries) before renaming","Rename to a target inside the same multi-destination mount tree instead of across differently-shaped mounts","Perform the rename per-nameservice directly (hdfs dfs -fs hdfs://nsX) if federation-wide atomicity is not required","Check 'hdfs dsadmin -listMountTable' for src/dst mount entries and fix asymmetries"],"exampleFix":"# before: src has ns0,ns1 destinations; dst only ns0 -> rejected\nhdfs dfs -fs hdfs://router -mv /multi/src /single/dst\n\n# after: make dst a multi-dest mount with the same ns set\nhdfs dsadmin -updateMount /single/dst ns0,ns1 /dst,/dst\nhdfs dfs -fs hdfs://router -mv /multi/src /single/dst","handlingStrategy":"validation","validationCode":"// Before renaming multi-destination mounts, confirm symmetric destination sets\nList<RemoteLocation> srcLocs = rpcServer.getLocationsForPath(src, false, false);\nList<RemoteLocation> dstLocs = rpcServer.getLocationsForPath(dst, false, false);\nSet<String> srcNs = srcLocs.stream().map(RemoteLocation::getNameserviceId).collect(Collectors.toSet());\nSet<String> dstNs = dstLocs.stream().map(RemoteLocation::getNameserviceId).collect(Collectors.toSet());\nif (!srcNs.equals(dstNs)) {\n  throw new IOException(\"Refusing rename: src/dst mount destinations differ: \" + srcNs + \" vs \" + dstNs);\n}","typeGuard":null,"tryCatchPattern":"try {\n  clientProtocol.rename(src, dst);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"number of remote locations\")) {\n    // align mount entries (same ns set for src and dst) or rename per-nameservice directly\n  } else { throw e; }\n}","preventionTips":["Design mount tables so multi-destination mounts have identical ns sets","Audit mount entries for asymmetry before federation-wide rename jobs","Prefer renames within a single mount subtree"],"tags":["hdfs","router-based-federation","rename","mount-table","multi-destination"],"backgroundTag":"invalid-operation-arguments","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}