apache/hadoop · error · AccessControlException

Cannot delete internal mount table directory: {}

Error message

Cannot delete internal mount table directory: {}

What it means

ViewFs.delete resolves the path and refuses deletion when the result is an internal mount-table directory (res.isInternalDir()) or the remaining path is the mount link itself (remainingPath == SlashPath), throwing AccessControlException("Cannot delete internal mount table directory: <path>"). The mount table's structural nodes are read-only by design — no fallback link is consulted on this path.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/viewfs/ViewFs.java:374

        throw e;
      }
    }
    assert(res.remainingPath != null);
    return res.targetFileSystem.createInternal(res.remainingPath, flag,
        absolutePermission, bufferSize, replication,
        blockSize, progress, checksumOpt,
        createParent);
  }

  @Override
  public boolean delete(final Path f, final boolean recursive)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    // If internal dir or target is a mount link (ie remainingPath is Slash)
    if (res.isInternalDir() || res.remainingPath == InodeTree.SlashPath) {
      throw new AccessControlException(
          "Cannot delete internal mount table directory: " + f);
    }
    return res.targetFileSystem.delete(res.remainingPath, recursive);
  }

  @Override
  public BlockLocation[] getFileBlockLocations(final Path f, final long start,
      final long len) throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    return
      res.targetFileSystem.getFileBlockLocations(res.remainingPath, start, len);
  }

  @Override
  public FileChecksum getFileChecksum(final Path f)
      throws AccessControlException, FileNotFoundException,

View on GitHub (pinned to 2add963021)

Solutions

  1. Delete concrete children inside mount points (e.g. viewfs:///user/alice/tmp) instead of the virtual ancestor
  2. Enumerate mount points via the viewfs API and delete within each mounted filesystem
  3. Catch AccessControlException and report 'read-only mount table node' instead of retrying
  4. Have admins remove the mount entry itself if the goal is to unmount

Example fix

// before
fc.delete(new Path("viewfs:///data"), true); // /data is a virtual dir -> throws

// after
for (MountPoint mp : ((ViewFs) fc.getDefaultFileSystem()).getMountPoints()) { /* delete inside mp */ }
// or target a concrete mounted child:
fc.delete(new Path("viewfs:///data/ds1/old"), true);
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean deletable(ViewFs vfs, Path p) throws IOException {
  String s = p.toUri().getPath();
  if (s.equals("/")) return false;
  return vfs.getMountPoints().stream()
      .map(mp -> mp.getMountedOnPath().toUri().getPath())
      .anyMatch(m -> s.equals(m) || s.startsWith(m + "/"));
}

Try / catch

try {
  deleted = fc.delete(p, true);
} catch (AccessControlException e) {
  // internal mount-table dir: not deletable via viewfs; delete inside mount points
}

Prevention

When it happens

Trigger: FileContext delete(true) on viewfs:/// (root) or on /user when only /user/alice is mounted; recursive deletes that start at a virtual container directory rather than inside a mount point.

Common situations: Cleanup jobs (`hadoop fs -rm -r viewfs:///...`) written before federation assuming plain HDFS; CI/EMR bootstrap scripts wiping scratch roots that are virtual dirs in the mount table.

Related errors


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