{"record":{"id":"3a2cb7b0541b7723","repo":"juicedata/juicefs","slug":"invalid-acl-acl-has-defaultentries-size","errorCode":null,"errorMessage":"Invalid ACL: ACL has \" + defaultEntries.size() + \" default entries, which exceeds maximum of \" + MAX_ENTRIES + \".","messagePattern":"Invalid ACL: ACL has \" \\+ defaultEntries\\.size\\(\\) \\+ \" default entries, which exceeds maximum of \" \\+ MAX_ENTRIES \\+ \"\\.","errorType":"validation","errorClass":"AclException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java","lineNumber":204,"sourceCode":"      }\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) {\n      throw new AclException(\"Invalid ACL: ACL has \" + defaultEntries.size() + \" default entries, which exceeds maximum of \" + MAX_ENTRIES + \".\");\n    }\n  }\n\n  private static void calculateMasks(List<AclEntry> aclBuilder, EnumMap<AclEntryScope, AclEntry> providedMask, EnumSet<AclEntryScope> maskDirty, EnumSet<AclEntryScope> scopeDirty) throws AclException {\n    EnumSet<AclEntryScope> scopeFound = EnumSet.noneOf(AclEntryScope.class);\n    EnumMap<AclEntryScope, FsAction> unionPerms = Maps.newEnumMap(AclEntryScope.class);\n    EnumSet<AclEntryScope> maskNeeded = EnumSet.noneOf(AclEntryScope.class);\n    // Determine which scopes are present, which scopes need a mask, and the\n    // union of group class permissions in each scope.\n    for (AclEntry entry : aclBuilder) {\n      scopeFound.add(entry.getScope());\n      if (entry.getType() == GROUP || entry.getName() != null) {\n        FsAction scopeUnionPerms = unionPerms.get(entry.getScope());\n        if (scopeUnionPerms == null) {\n          scopeUnionPerms = FsAction.NONE;\n        }\n        unionPerms.put(entry.getScope(), scopeUnionPerms.or(entry.getPermission()));\n      }","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java#L186-L222","documentation":"checkMaxEntries' limit check for the DEFAULT scope: when a default ACL (inheritance ACL on a directory) contains more than MAX_ENTRIES entries it is rejected. Same rationale as the access-scope cap — bounded metadata size per inode.","triggerScenarios":"mergeAclEntries/replaceAclEntries producing a DEFAULT-scope ACL with more than MAX_ENTRIES entries, typically by repeatedly merging named default user/group entries into a directory's ACL.","commonSituations":"Setting inheritance rules for many named users on a directory; repeated merges of default entries across scripts until the cap is crossed.","solutions":["Trim default entries so only necessary inheritance rules remain; default entries only need base trio plus genuinely inherited grants.","Use replaceAclEntries with a compact spec instead of accumulating merges.","Encode bulk inheritance via groups rather than per-user default entries."],"exampleFix":"// before\nmergeAclEntries(dir, \"default:user:u1:rwx,default:user:u2:rwx,...\"); // > MAX_ENTRIES default entries\n// after\nmergeAclEntries(dir, \"default:user::rwx,default:group::r-x,default:group:team:rwx,default:other::r--\");","handlingStrategy":"validation","validationCode":"if (defaultEntries.size() > MAX_ENTRIES) {\n  throw new IllegalArgumentException(\"too many default entries: \" + defaultEntries.size());\n}","typeGuard":null,"tryCatchPattern":"try {\n  mergeAclEntries(dir, spec);\n} catch (AclException e) {\n  if (e.getMessage().contains(\"default entries, which exceeds maximum\")) {\n    spec = pruneDefaultEntries(spec);\n    replaceAclEntries(dir, spec);\n  } else throw e;\n}","preventionTips":["Keep default ACLs minimal — base trio plus needed group grants.","Track entry counts when repeatedly merging into directory ACLs.","Periodically rewrite directory ACLs with a compact replacement spec."],"tags":["acl","java","limit-exceeded","default-acl"],"backgroundTag":"value-out-of-range","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}