apache/hadoop · error · AccessControlException
The xattr 'security.hdfs.unreadable.by.superuser' can not be
Error message
The xattr 'security.hdfs.unreadable.by.superuser' can not be deleted.
What it means
security.hdfs.unreadable.by.superuser is an internal protection flag: once set by a privileged client it hides the file's content even from the HDFS superuser. unprotectedRemoveXAttrs rejects any removal attempt with AccessControlException; there is deliberately no API to delete it, because that would defeat its security purpose. The adjacent guard likewise forbids deleting the encryption-zone key id xattr.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirXAttrOp.java:249
throws AccessControlException {
if (existingXAttrs == null || existingXAttrs.isEmpty() ||
toFilter == null || toFilter.isEmpty()) {
return existingXAttrs;
}
// Populate a new list with XAttrs that pass the filter
List<XAttr> newXAttrs =
Lists.newArrayListWithCapacity(existingXAttrs.size());
for (XAttr a : existingXAttrs) {
boolean add = true;
for (ListIterator<XAttr> it = toFilter.listIterator(); it.hasNext()
;) {
XAttr filter = it.next();
Preconditions.checkArgument(
!KEYID_XATTR.equalsIgnoreValue(filter),
"The encryption zone xattr should never be deleted.");
if (UNREADABLE_BY_SUPERUSER_XATTR.equalsIgnoreValue(filter)) {
throw new AccessControlException("The xattr '" +
SECURITY_XATTR_UNREADABLE_BY_SUPERUSER + "' can not be deleted.");
}
if (a.equalsIgnoreValue(filter)) {
add = false;
it.remove();
filtered.add(filter);
break;
}
}
if (add) {
newXAttrs.add(a);
}
}
return newXAttrs;
}
public static INode unprotectedSetXAttrs(View on GitHub (pinned to 2add963021)
Solutions
- Skip protected attributes in removal loops: never touch security.hdfs.unreadable.by.superuser, and filter raw./system. namespaces
- To actually drop the protection, copy the file content to a new file (the xattr does not carry over) and swap names
- Fix bulk tooling to filter xattrs by namespace before calling removeXAttr
Example fix
// before: strip everything
for (String name : fs.listXAttrs(path)) {
fs.removeXAttr(path, name); // AccessControlException on protected xattr
}
// after: skip protected/internal namespaces
for (String name : fs.listXAttrs(path)) {
if (!name.startsWith("security.") && !name.startsWith("system.")
&& !name.startsWith("raw.")) {
fs.removeXAttr(path, name);
}
} Defensive patterns
Strategy: validation
Validate before calling
for (String name : fs.listXAttrs(path)) {
if (!isProtectedXattr(name)) {
fs.removeXAttr(path, name);
}
} Type guard
static boolean isProtectedXattr(String name) {
return "security.hdfs.unreadable.by.superuser".equals(name)
|| name.startsWith("system.")
|| name.startsWith("raw.");
} Try / catch
try {
fs.removeXAttr(path, name);
} catch (AccessControlException e) {
// protected attribute: skip it in bulk-removal loops instead of failing
} Prevention
- Never include security.hdfs.unreadable.by.superuser or raw./system. xattrs in removal sets
- Filter by namespace in bulk tools before calling removeXAttr
- To drop the protection, copy file content to a new file rather than deleting the attribute
When it happens
Trigger: removeXAttr (or bulk delete-all-xattrs logic) that includes security.hdfs.unreadable.by.superuser in the list; the same method also rejects the raw encryption-zone keyid xattr via Preconditions.
Common situations: Generic xattr dump/restore, anonymization, or cleanup tools that enumerate and strip every attribute; migration scripts that try to normalize xattrs across trees.
Related errors
- Can only set 'security.hdfs.unreadable.by.superuser' on a fi
- {} doesn't support setXAttr
- {} doesn't support getXAttr
- {} doesn't support getXAttrs
- '{}' copy from '/.reserved/raw' to non '/.reserved/raw'. Eit
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/825309f52b1971da.
Report an issue: GitHub.