apache/hadoop · error · AccessControlException

Permission denied rename {}({}) to {}({}) Reason={}

Error message

Permission denied rename {}({}) to {}({}) Reason={}

What it means

Before submitting a fed rename, RouterFederationRename.checkPermission verifies the caller has write access to the parent directories of both src and dst in the actual subclusters. Any AccessControlException from that check (HDFS permissions, or kerberos proxy-user impersonation being refused) is rethrown with this message that records src/dst RemoteLocations and the underlying reason.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterFederationRename.java:166

      throws IOException {
    try {
      if (UserGroupInformation.isSecurityEnabled()) {
        // In security mode, check permission as remote user proxy by router
        // user.
        String remoteUserName = NameNode.getRemoteUser().getShortUserName();
        UserGroupInformation proxyUser = UserGroupInformation
            .createProxyUser(remoteUserName,
                UserGroupInformation.getLoginUser());
        proxyUser.doAs((PrivilegedExceptionAction<Object>) () -> {
          checkRenamePermission(src, dst);
          return null;
        });
      } else {
        // In simple mode, check permission as remote user directly.
        checkRenamePermission(src, dst);
      }
    } catch (AccessControlException e) {
      throw new AccessControlException(
          "Permission denied rename " + src.getSrc() + "(" + src + ") to " + dst
              .getSrc() + "(" + dst + ") Reason=" + e.getMessage());
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new InterruptedIOException(
          "Router Federation Rename is interrupted while checking permission.");
    }
  }

  private void checkRenamePermission(RemoteLocation srcLoc,
      RemoteLocation dstLoc) throws IOException {
    // check src path permission.
    Path srcPath =
        new Path("hdfs://" + srcLoc.getNameserviceId() + srcLoc.getDest());
    srcPath.getFileSystem(conf).access(srcPath.getParent(), FsAction.WRITE);
    // check dst path permission.
    Path dstPath =
        new Path("hdfs://" + dstLoc.getNameserviceId() + dstLoc.getDest());

View on GitHub (pinned to 2add963021)

Solutions

  1. Check the Reason= suffix: it carries the original AccessControlException (permission vs proxying)
  2. Grant WRITE on the parent directories of both src and dst in their respective subclusters (hdfs dfs -chmod / hdfs dfs -chown)
  3. If the reason is proxy-user refusal, configure hadoop.proxyuser.<routerUser>.hosts/groups to cover the client, then restart the Namenode/refresh proxy user mappings
  4. Retry the rename as a user that owns or can write both parent directories

Example fix

# before: destination parent not writable by caller
hdfs dfs -fs hdfs://ns1 -ls -d /target        # owned by other:user, mode 755
# after
hdfs dfs -fs hdfs://ns1 -chmod 777 /target   # or chown to the calling user, or use hdfs dfs -setfacl
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check WRITE on both parents in their subclusters, mirroring the router's check
for (RemoteLocation loc : new RemoteLocation[]{srcLoc, dstLoc}) {
  Path p = new Path("hdfs://" + loc.getNameserviceId() + loc.getDest());
  p.getFileSystem(conf).access(p.getParent(), FsAction.WRITE);
}

Try / catch

try {
  dfs.rename(src, dst);
} catch (AccessControlException ace) {
  if (ace.getMessage() != null && ace.getMessage().startsWith("Permission denied rename")) {
    // message embeds the original Reason=; fix WRITE on parents or proxy-user config accordingly
  }
  throw ace;
}

Prevention

When it happens

Trigger: checkPermission runs as the caller (directly in simple auth, or via UserGroupInformation.createProxyUser(remoteUserName, loginUser).doAs in kerberos): the underlying checkRenamePermission calls FileSystem.access(path.getParent(), FsAction.WRITE) on 'hdfs://<nameservice>/...' for both sides; lacking WRITE on either parent, or the router user not being allowed to proxy for the remote user, throws.

Common situations: User without write permission on the destination parent; ownership differs between subclusters; hadoop.proxyuser.<router-user>.groups/hosts not configured so the kerberos proxy doAs fails; running rename as a service account that only has read access.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/7f81799896c66409. Report an issue: GitHub.