{"record":{"id":"01f57414351e414a","repo":"juicedata/juicefs","slug":"invalid-acl-the-user-group-and-other-entries-are","errorCode":null,"errorMessage":"Invalid ACL: the user, group and other entries are required.","messagePattern":"Invalid ACL: the user, group and other entries are required\\.","errorType":"validation","errorClass":"AclException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java","lineNumber":185,"sourceCode":"    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.\");\n        }\n      }\n    }\n    return Collections.unmodifiableList(aclBuilder);\n  }\n\n  private static void checkMaxEntries(ScopedAclEntries scopedEntries) throws AclException {\n    List<AclEntry> accessEntries = scopedEntries.getAccessEntries();\n    List<AclEntry> defaultEntries = scopedEntries.getDefaultEntries();\n    if (accessEntries.size() > MAX_ENTRIES) {\n      throw new AclException(\"Invalid ACL: ACL has \" + accessEntries.size() + \" access entries, which exceeds maximum of \" + MAX_ENTRIES + \".\");\n    }\n    if (defaultEntries.size() > MAX_ENTRIES) {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java#L167-L203","documentation":"buildAndValidateAcl in AclTransformation.java enforces POSIX ACL invariants before any ACL modification (filter, merge, replace). Every ACL must contain base ACCESS entries of type USER, GROUP and OTHER; binary search over the sorted access entries shows one of these three required entries is missing. This mirrors Hadoop's AclTransformation, from which this utility was ported.","triggerScenarios":"Calling filterAclEntriesByAclSpec, mergeAclEntries or replaceAclEntries with an ACL spec/list that removes or omits one of the required ACCESS entries: user, group, or other (scope=ACCESS).","commonSituations":"Building an ACL string that starts with named users/groups only (e.g. 'user:bob:rwx'); filtering out the 'other' entry by mistake; parsing a spec like 'group::rwx,user:alice:r--' with no user::/group::/other:: base entries.","solutions":["Add the missing base access entry (user::, group::, other::) to the ACL spec before calling the transformation API.","If filtering, verify the AclSpec does not match the required base entries and remove those patterns.","When replacing an ACL, include all three base entries in the replacement spec."],"exampleFix":"// before\nreplaceAclEntries(path, \"user:alice:rwx,user:bob:r-x\");\n// after\nreplaceAclEntries(path, \"user::rwx,user:alice:rwx,user:bob:r-x,group::r-x,other::r--\");","handlingStrategy":"validation","validationCode":"def has_base_access_entries(entries):\n    types = {e.getType() for e in entries if e.getScope() == AclEntryScope.ACCESS}\n    return {AclEntryType.USER, AclEntryType.GROUP, AclEntryType.OTHER} <= types","typeGuard":null,"tryCatchPattern":"try {\n  replaceAclEntries(path, spec);\n} catch (AclException e) {\n  if (e.getMessage().contains(\"user, group and other entries are required\")) {\n    spec = addBaseEntries(spec); // append user::, group::, other:: and retry\n    replaceAclEntries(path, spec);\n  } else throw e;\n}","preventionTips":["Always start ACL specs from a full base trio (user::, group::, other::).","Never include user::/group::/other:: patterns in filter specs.","Unit-test ACL builders to assert the three base access entries exist."],"tags":["acl","java","validation"],"backgroundTag":"missing-required-argument","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"}