{"record":{"id":"7e18829e178f86b0","repo":"juicedata/juicefs","slug":"invalid-acl-acl-has-accessentries-size","errorCode":null,"errorMessage":"Invalid ACL: ACL has \" + accessEntries.size() + \" access entries, which exceeds maximum of \" + MAX_ENTRIES + \".","messagePattern":"Invalid ACL: ACL has \" \\+ accessEntries\\.size\\(\\) \\+ \" access 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":201,"sourceCode":"      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) {\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;","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java#L183-L219","documentation":"checkMaxEntries enforces the POSIX ACL size limit: a filesystem ACL may hold at most MAX_ENTRIES entries per scope. The access scope of the supplied ACL exceeds this cap, so the ACL is rejected before being applied. Keeping ACLs bounded prevents unbounded metadata growth in the metadata engine.","triggerScenarios":"mergeAclEntries or replaceAclEntries with a spec producing more than MAX_ENTRIES (see AclTransformation.java, typically 32) ACCESS-scope entries, e.g. adding named users/groups past the limit.","commonSituations":"Bulk-granting access to dozens of users on one path via merge; scripted ACL application over a generated list of principals; migrating ACLs from another system with a higher entry limit.","solutions":["Reduce the number of access entries — replace individual user entries with group-based entries.","Use replace instead of merge so the resulting ACL stays under the limit rather than accumulating.","Split permissions across group memberships managed outside the ACL (e.g. a POSIX group) and grant one group entry."],"exampleFix":"// before\nmergeAclEntries(path, joinSpec(1000 namedUserEntries)); // exceeds MAX_ENTRIES\n// after\nmergeAclEntries(path, \"group::r-x,group:team-a:r-x,other::r--\"); // one group entry for many users","handlingStrategy":"validation","validationCode":"if (accessEntries.size() > MAX_ENTRIES) {\n  throw new IllegalArgumentException(\"too many access entries: \" + accessEntries.size());\n}","typeGuard":null,"tryCatchPattern":"try {\n  mergeAclEntries(path, spec);\n} catch (AclException e) {\n  if (e.getMessage().contains(\"exceeds maximum\")) {\n    spec = compactSpecViaGroups(spec);\n    replaceAclEntries(path, spec);\n  } else throw e;\n}","preventionTips":["Count parsed entries and cap the spec before calling the API.","Prefer group entries over per-user entries for large grants.","Use replace (not merge) in scripts to avoid unbounded accumulation."],"tags":["acl","java","limit-exceeded"],"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"}