{"record":{"id":"0f87db7598b24faa","repo":"apache/hadoop","slug":"router-federation-rename-can-t-rename-snapshot-pat","errorCode":null,"errorMessage":"Router federation rename can't rename snapshot path. src={}({})","messagePattern":"Router federation rename can't rename snapshot path\\. src=(.+?)\\((.+?)\\)","errorType":"exception","errorClass":"AccessControlException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterFederationRename.java","lineNumber":192,"sourceCode":"  }\n\n  private void checkRenamePermission(RemoteLocation srcLoc,\n      RemoteLocation dstLoc) throws IOException {\n    // check src path permission.\n    Path srcPath =\n        new Path(\"hdfs://\" + srcLoc.getNameserviceId() + srcLoc.getDest());\n    srcPath.getFileSystem(conf).access(srcPath.getParent(), FsAction.WRITE);\n    // check dst path permission.\n    Path dstPath =\n        new Path(\"hdfs://\" + dstLoc.getNameserviceId() + dstLoc.getDest());\n    dstPath.getFileSystem(conf).access(dstPath.getParent(), FsAction.WRITE);\n  }\n\n  static void checkSnapshotPath(RemoteLocation src, RemoteLocation dst)\n      throws AccessControlException {\n    if (src.getDest()\n        .contains(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR + Path.SEPARATOR)) {\n      throw new AccessControlException(\n          \"Router federation rename can't rename snapshot path. src=\" + src\n              .getSrc() + \"(\" + src + \")\");\n    }\n    if (dst.getDest()\n        .contains(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR + Path.SEPARATOR)) {\n      throw new AccessControlException(\n          \"Router federation rename can't rename snapshot path. dst=\" + dst\n              .getSrc() + \"(\" + dst + \")\");\n    }\n  }\n\n  /**\n   * Build router federation rename job moving data from src to dst.\n   * @param srcNs the source namespace id.\n   * @param dstNs the dst namespace id.\n   * @param src the source path.\n   * @param dst the dst path.\n   */","sourceCodeStart":174,"sourceCodeEnd":210,"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#L174-L210","documentation":"Router federation rename refuses to operate on snapshot paths: RouterFederationRename.checkSnapshotPath rejects any src whose remote destination path contains '/.snapshot/' (HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR + Path.SEPARATOR). Distcp-based fed rename cannot faithfully move snapshot metadata, so the operation is blocked up front with an AccessControlException.","triggerScenarios":"rename(src, dst) across namespaces where the resolved src RemoteLocation destination contains a /.snapshot/ segment, e.g. renaming /mount/.snapshot/snap1/dir or any path addressing an element inside a snapshot.","commonSituations":"Users or tooling that references snapshot-relative paths (backup jobs, snapshot diff tooling) attempt a cross-mount rename; shell completion or scripts accidentally pin a .snapshot path as the source.","solutions":["Rename the live (non-snapshot) path instead: address the source directory itself, not /path/.snapshot/<snap>/...","If snapshot data must be preserved across namespaces, use distcp -snapshotDiff or copy the needed snapshot content explicitly to the target cluster","Delete stale snapshots if the .snapshot reference is accidental, then retry the plain rename"],"exampleFix":"# before\nhdfs dfs -fs hdfs://router -mv /src/.snapshot/snap1/data /dstmount/data\n# after (rename the live path; snapshot content is copied separately if needed)\nhdfs dfs -fs hdfs://router -mv /src/data /dstmount/data","handlingStrategy":"validation","validationCode":"// Mirror the router check before issuing the rename\nif (src.contains(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR + Path.SEPARATOR)) {\n  throw new IllegalArgumentException(\"Fed rename cannot use snapshot src path: \" + src);\n}","typeGuard":"boolean isSnapshotPath(String path) {\n  return path != null && path.contains(\"/.snapshot/\");\n}","tryCatchPattern":"try {\n  dfs.rename(src, dst);\n} catch (AccessControlException ace) {\n  if (ace.getMessage() != null && ace.getMessage().contains(\"can't rename snapshot path. src=\")) {\n    // reissue against the live path instead of /path/.snapshot/snap/...\n  }\n  throw ace;\n}","preventionTips":["Never construct source paths referencing /.snapshot/ for mutations; snapshots are read-only","Validate rename operands client-side with a simple /.snapshot/ substring check","Use distcp -snapshotDiff when snapshot data genuinely must move between namespaces"],"tags":["hdfs","router","federation","rename","snapshot","validation"],"backgroundTag":"snapshot-path-not-supported","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}