{"record":{"id":"f3c8faefb776870a","repo":"apache/hadoop","slug":"permission-denied-while-accessing-mount-table","errorCode":null,"errorMessage":"Permission denied while accessing mount table {}: user {} does not have {} permissions.","messagePattern":"Permission denied while accessing mount table (.+?): user (.+?) does not have (.+?) permissions\\.","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/RouterPermissionChecker.java","lineNumber":94,"sourceCode":"\n    FsPermission mode = mountTable.getMode();\n    if (getUser().equals(mountTable.getOwnerName())\n        && mode.getUserAction().implies(access)) {\n      return;\n    }\n\n    if (isMemberOfGroup(mountTable.getGroupName())\n        && mode.getGroupAction().implies(access)) {\n      return;\n    }\n\n    if (!getUser().equals(mountTable.getOwnerName())\n        && !isMemberOfGroup(mountTable.getGroupName())\n        && mode.getOtherAction().implies(access)) {\n      return;\n    }\n\n    throw new AccessControlException(\n        \"Permission denied while accessing mount table \"\n            + mountTable.getSourcePath()\n            + \": user \" + getUser() + \" does not have \" + access.toString()\n            + \" permissions.\");\n  }\n\n  /**\n   * Check the superuser privileges of the current RPC caller. This method is\n   * based on Datanode#checkSuperuserPrivilege().\n   * @throws AccessControlException If the user is not authorized.\n   */\n  @Override\n  public void checkSuperuserPrivilege() throws  AccessControlException {\n\n    // Try to get the ugi in the RPC call.\n    UserGroupInformation ugi = null;\n    try {\n      ugi = NameNode.getRemoteUser();","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterPermissionChecker.java#L76-L112","documentation":"When router permission checks (dfs.federation.router.permission.enable) are on, RouterPermissionChecker applies POSIX-style owner/group/other mode checks to mount-table entries. If the caller is neither the owner, nor in the entry's group, nor covered by the other-mode with an implying access, this AccessControlException reports the mount path, the user, and the missing access (READ/WRITE).","triggerScenarios":"An admin RPC (RouterAdminServer: add/update/remove mount table, or any path checked via checkMountTable) issued by a user whose permissions on the target MountTable record do not imply the required FSAction - e.g. mode 755 entry and a non-owner attempting a write-type modification.","commonSituations":"Multiple teams sharing router admin duties with per-mount ownership; a mount entry created with restrictive owner:group:mode and later modified by another team; permission model enabled after mounts were created with defaults owned by a different user.","solutions":["Check the entry's owner/group/mode: hdfs dfsrouteradmin -listMountTable and fix ownership with hdfs dfsrouteradmin -update <path> -owner <user> -group <grp> -mode <mode> (run by the current owner or the router super user)","Run the admin operation as the router super user (the user running the Router) or a member of dfs.permissions.superusergroup","Grant the acting user the needed access via mode bits (e.g. 775 for group-write) instead of per-user exceptions"],"exampleFix":"# before: entry /data owned by teamA:teamA mode 755, teamB tries to update\nhdfs dfsrouteradmin -update /data -ns ns1 -dst /data   # Permission denied\n# after (as owner or super user)\nhdfs dfsrouteradmin -update /data -owner teamA -group datadmins -mode 775","handlingStrategy":"try-catch","validationCode":"// Check mount entry permission before issuing the admin call (mirror of checker logic)\nMountTable mt = mountTableStore.get(new PathScanner(path)); // or fetch matching entry\nFsPermission mode = mt.getMode();\nString user = UserGroupInformation.getCurrentUser().getShortUserName();\nboolean allowed = user.equals(mt.getOwnerName()) && mode.getUserAction().implies(FsAction.WRITE)\n    || userInGroup(mt.getGroupName()) && mode.getGroupAction().implies(FsAction.WRITE)\n    || mode.getOtherAction().implies(FsAction.WRITE);\nif (!allowed) throw new AccessControlException(\"skip RPC: no write on \" + mt.getSourcePath());","typeGuard":null,"tryCatchPattern":"try {\n  client.getMountTableAdmin().updateMountTable(entry);\n} catch (AccessControlException ace) {\n  if (ace.getMessage() != null && ace.getMessage().startsWith(\"Permission denied while accessing mount table\")) {\n    // run as entry owner, join the entry group, or have the owner widen the mode\n  }\n  throw ace;\n}","preventionTips":["Set explicit owner/group/mode on every mount entry at creation time","Give administration teams group-based access (mode 775) instead of relying on a single owner","Reserve direct-superuser admin operations for break-glass procedures"],"tags":["hdfs","router","federation","mount-table","permission-denied","access-control","admin-api"],"backgroundTag":"permission-denied","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}