{"record":{"id":"eabeed16d4b7cf4a","repo":"apache/hadoop","slug":"user-pc-getuser-is-not-a-super-user-no","errorCode":null,"errorMessage":"\"User \" + pc.getUser() + \" is not a super user (non-super user cannot change owner).\"","messagePattern":"\"User \" \\+ pc\\.getUser\\(\\) \\+ \" is not a super user \\(non-super user cannot change owner\\)\\.\"","errorType":"exception","errorClass":"AccessControlException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java","lineNumber":97,"sourceCode":"    INodesInPath iip;\n    boolean changed;\n    fsd.writeLock();\n    try {\n      iip = fsd.resolvePath(pc, src, DirOp.WRITE);\n      fsd.checkOwner(pc, iip);\n      // At this point, the user must be either owner or super user.\n      // superuser: can change owner to a different user,\n      // change owner group to any group\n      // owner: can't change owner to a different user but can change owner\n      // group to different group that the user belongs to.\n      if ((username != null && !pc.getUser().equals(username)) ||\n          (group != null && !pc.isMemberOfGroup(group))) {\n        try {\n          // check if the user is superuser\n          pc.checkSuperuserPrivilege(iip.getPath());\n        } catch (AccessControlException e) {\n          if (username != null && !pc.getUser().equals(username)) {\n            throw new AccessControlException(\"User \" + pc.getUser()\n                + \" is not a super user (non-super user cannot change owner).\");\n          }\n          if (group != null && !pc.isMemberOfGroup(group)) {\n            throw new AccessControlException(\n                \"User \" + pc.getUser() + \" does not belong to \" + group);\n          }\n        }\n      }\n      changed = unprotectedSetOwner(fsd, iip, username, group);\n    } finally {\n      fsd.writeUnlock();\n    }\n    if (changed) {\n      fsd.getEditLog().logSetOwner(iip.getPath(), username, group);\n    }\n    return fsd.getAuditFileInfo(iip);\n  }\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java#L79-L115","documentation":"setOwner implements classic UNIX chown rules: a file owner may change the group, but only a superuser may change the owner. When the requested username differs from the caller and the superuser privilege check (checkSuperuserPrivilege) fails, FSDirAttrOp.setOwner rethrows this clearer AccessControlException.","triggerScenarios":"DistributedFileSystem.setOwner(path, newOwner, ...) or 'hdfs dfs -chown newuser:file' where newOwner != current caller and the caller is not the HDFS superuser (typically the 'hdfs' user) or a member of the supergroup.","commonSituations":"ETL pipelines trying to chown outputs to service accounts; jobs staging data as one user then transferring ownership to another; directory-restructuring scripts run with ordinary user credentials.","solutions":["Run the ownership change as the HDFS superuser (kinit as hdfs / 'sudo -u hdfs hdfs dfs -chown ...').","If only a group change was intended, pass username null: setOwner(path, null, group) - allowed for the file owner.","For recurring needs, configure hadoop proxyuser (doAs) so an approved service performs ownership changes on behalf of users instead of widening superuser access."],"exampleFix":"// before: fails unless caller is superuser\nfs.setOwner(path, \"etl_svc\", null);\n\n// after: only the owner-changing call needs elevation; group change does not\nif (ugi.getShortUserName().equals(currentOwner) || isSuperUser(ugi)) {\n  fs.setOwner(path, \"etl_svc\", null); // run this branch as hdfs via doAs\n} else {\n  throw new AccessControlException(\"Only superuser may chown \" + path);\n}","handlingStrategy":"validation","validationCode":"UserGroupInformation ugi = UserGroupInformation.getCurrentUser();\nFileStatus st = fs.getFileStatus(path);\nboolean changingOwner = newOwner != null && !ugi.getShortUserName().equals(newOwner);\nif (changingOwner && !ugi.getShortUserName().equals(\"hdfs\")) {\n  throw new AccessControlException(\"Run chown-to-other-user as the HDFS superuser\");\n}\nfs.setOwner(path, newOwner, group);","typeGuard":null,"tryCatchPattern":"try {\n  fs.setOwner(path, newOwner, null);\n} catch (AccessControlException e) {\n  if (e.getMessage().contains(\"cannot change owner\")) {\n    // re-run under the hdfs principal via doAs; do not strip the check\n  }\n}","preventionTips":["Run ownership-transfer steps in a dedicated elevated stage (hdfs principal / proxyuser).","Remember setOwner(path, null, group) is legal for owners - use it when only the group changes."],"tags":["hdfs","permissions","chown","access-control"],"backgroundTag":"permission-denied-superuser-required","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}