{"record":{"id":"81ee88b3280b3950","repo":"juicedata/juicefs","slug":"invalid-acl-this-entry-type-must-not-have-a-name","errorCode":null,"errorMessage":"Invalid ACL: this entry type must not have a name: \" + entry + \".","messagePattern":"Invalid ACL: this entry type must not have a name: \" \\+ entry \\+ \"\\.","errorType":"validation","errorClass":"AclException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java","lineNumber":172,"sourceCode":"\n  public static final Comparator<AclEntry> ACL_ENTRY_COMPARATOR = new Comparator<AclEntry>() {\n    @Override\n    public int compare(AclEntry entry1, AclEntry entry2) {\n      return ComparisonChain.start().compare(entry1.getScope(), entry2.getScope(), Ordering.explicit(ACCESS, DEFAULT)).compare(entry1.getType(), entry2.getType(), Ordering.explicit(USER, GROUP, MASK, OTHER)).compare(entry1.getName(), entry2.getName(), Ordering.natural().nullsFirst()).result();\n    }\n  };\n\n  public static List<AclEntry> buildAndValidateAcl(ArrayList<AclEntry> aclBuilder) throws AclException {\n    aclBuilder.trimToSize();\n    Collections.sort(aclBuilder, ACL_ENTRY_COMPARATOR);\n    // Full iteration to check for duplicates and invalid named entries.\n    AclEntry prevEntry = null;\n    for (AclEntry entry : aclBuilder) {\n      if (prevEntry != null && ACL_ENTRY_COMPARATOR.compare(prevEntry, entry) == 0) {\n        throw new AclException(\"Invalid ACL: multiple entries with same scope, type and name.\");\n      }\n      if (entry.getName() != null && (entry.getType() == MASK || entry.getType() == OTHER)) {\n        throw new AclException(\"Invalid ACL: this entry type must not have a name: \" + entry + \".\");\n      }\n      prevEntry = entry;\n    }\n\n    ScopedAclEntries scopedEntries = new ScopedAclEntries(aclBuilder);\n    checkMaxEntries(scopedEntries);\n\n    // Search for the required base access entries.  If there is a default ACL,\n    // then do the same check on the default entries.\n    for (AclEntryType type : EnumSet.of(USER, GROUP, OTHER)) {\n      AclEntry accessEntryKey = new AclEntry.Builder().setScope(ACCESS).setType(type).build();\n      if (Collections.binarySearch(scopedEntries.getAccessEntries(), accessEntryKey, ACL_ENTRY_COMPARATOR) < 0) {\n        throw new AclException(\"Invalid ACL: the user, group and other entries are required.\");\n      }\n      if (!scopedEntries.getDefaultEntries().isEmpty()) {\n        AclEntry defaultEntryKey = new AclEntry.Builder().setScope(DEFAULT).setType(type).build();\n        if (Collections.binarySearch(scopedEntries.getDefaultEntries(), defaultEntryKey, ACL_ENTRY_COMPARATOR) < 0) {\n          throw new AclException(\"Invalid default ACL: the user, group and other entries are required.\");","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java#L154-L190","documentation":"AclValidationException from buildAndValidateAcl: the ACL specification contains a named entry for a type that must be unnamed. Only USER (when not the owner), GROUP, and default entries may carry a name; named OWNER, MASK, or OTHER entries are structurally invalid and rejected during ACL validation before anything reaches JuiceFS.","triggerScenarios":"Calling any AclTransformation entry point (mergeAclEntries, replaceAclEntries, filterAclEntriesByAclSpec) with a spec containing e.g. type=MASK with name set, or default:other:someName:rwx.","commonSituations":"Building AclEntries programmatically and accidentally setting the name for MASK/OTHER; parsing ACL strings incorrectly and attaching a name to every entry; migrating ACLs from systems with different entry grammar.","solutions":["Remove the name from MASK/OTHER entries before applying the spec","Only set names for USER/GROUP entries (named user/group ACLs)","Fix the ACL string parser so the name field is null for mask/other lines","Validate the AclSpec client-side before calling the transformation API"],"exampleFix":"// before\nnew AclEntry.Builder().setType(AclEntryType.MASK).setName(\"mask-owner\").setPermission(FULL).build()\n// after\nnew AclEntry.Builder().setType(AclEntryType.MASK).setPermission(FULL).build()","handlingStrategy":"validation","validationCode":"for (AclEntry e : aclSpec.getEntries()) {\n  if (e.getName() != null && (e.getType() == AclEntryType.MASK || e.getType() == AclEntryType.OTHER))\n    throw new IllegalArgumentException(\"MASK/OTHER must not have a name: \" + e);\n}","typeGuard":"boolean hasValidEntryTypes(List<AclEntry> entries) {\n  return entries.stream().noneMatch(e -> e.getName() != null &&\n    (e.getType() == AclEntryType.MASK || e.getType() == AclEntryType.OTHER));\n}","tryCatchPattern":"try {\n  AclTransformation.replaceAclEntries(...);\n} catch (AclException e) {\n  if (e.getMessage().contains(\"must not have a name\")) {\n    LOG.error(\"Strip names from MASK/OTHER entries: \" + e.getMessage());\n  } else throw e;\n}","preventionTips":["Only set names on USER/GROUP entries","Fix ACL parsers to leave name null for mask/other lines","Validate specs client-side before transformation calls"],"tags":["acl","validation","hadoop","permissions"],"backgroundTag":"schema-validation-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}