juicedata/juicefs · error · AclException

Invalid ACL: multiple entries with same scope, type and name

Error message

Invalid ACL: multiple entries with same scope, type and name.

What it means

AclTransformation.buildAndValidateAcl throws AclException when, after sorting, two ACL entries compare equal (same scope, type and name) — duplicates are not representable in a valid ACL. Called by filterAclEntriesByAclSpec, mergeAclEntries and replaceAclEntries.

Source

Thrown at sdk/java/src/main/java/io/juicefs/utils/AclTransformation.java:169

  private AclTransformation() {
  }

  public static final Comparator<AclEntry> ACL_ENTRY_COMPARATOR = new Comparator<AclEntry>() {
    @Override
    public int compare(AclEntry entry1, AclEntry entry2) {
      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();
    }
  };

  public static List<AclEntry> buildAndValidateAcl(ArrayList<AclEntry> aclBuilder) throws AclException {
    aclBuilder.trimToSize();
    Collections.sort(aclBuilder, ACL_ENTRY_COMPARATOR);
    // Full iteration to check for duplicates and invalid named entries.
    AclEntry prevEntry = null;
    for (AclEntry entry : aclBuilder) {
      if (prevEntry != null && ACL_ENTRY_COMPARATOR.compare(prevEntry, entry) == 0) {
        throw new AclException("Invalid ACL: multiple entries with same scope, type and name.");
      }
      if (entry.getName() != null && (entry.getType() == MASK || entry.getType() == OTHER)) {
        throw new AclException("Invalid ACL: this entry type must not have a name: " + entry + ".");
      }
      prevEntry = entry;
    }

    ScopedAclEntries scopedEntries = new ScopedAclEntries(aclBuilder);
    checkMaxEntries(scopedEntries);

    // Search for the required base access entries.  If there is a default ACL,
    // then do the same check on the default entries.
    for (AclEntryType type : EnumSet.of(USER, GROUP, OTHER)) {
      AclEntry accessEntryKey = new AclEntry.Builder().setScope(ACCESS).setType(type).build();
      if (Collections.binarySearch(scopedEntries.getAccessEntries(), accessEntryKey, ACL_ENTRY_COMPARATOR) < 0) {
        throw new AclException("Invalid ACL: the user, group and other entries are required.");
      }
      if (!scopedEntries.getDefaultEntries().isEmpty()) {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Deduplicate the AclSpec before applying (use a Set keyed by scope/type/name)
  2. Use replaceAclEntries with a clean full ACL list instead of merging overlapping specs
  3. Inspect the current ACL (getAclStatus) and remove the duplicate entry
  4. Fix the tooling/script that generates the spec to avoid repeats

Example fix

// before
Set<AclEntry> entries = new HashSet<>(); // preserves last-wins on name
// after
Map<String, AclEntry> byKey = new LinkedHashMap<>();
spec.forEach(e -> byKey.put(e.getScope()+":"+e.getType()+":"+e.getName(), e));
AclSpec deduped = new AclSpec(new ArrayList<>(byKey.values()));
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (AclEntry e : aclSpec.getEntries()) {
  String k = e.getScope()+":"+e.getType()+":"+e.getName();
  if (!seen.add(k)) throw new IllegalArgumentException("Duplicate ACL entry: " + k);
}

Type guard

boolean isDuplicateFree(List<AclEntry> entries) {
  Set<String> keys = new HashSet<>();
  for (AclEntry e : entries)
    if (!keys.add(e.getScope()+":"+e.getType()+":"+e.getName())) return false;
  return true;
}

Try / catch

try {
  AclTransformation.mergeAclEntries(...);
} catch (AclException e) {
  if (e.getMessage().contains("multiple entries with same scope, type and name")) {
    LOG.error("Deduplicate the AclSpec before applying");
  } else throw e;
}

Prevention

When it happens

Trigger: Submitting an AclSpec (via setAcl/modifyAcl paths) containing two entries that normalize to the same scope+type+name, e.g. duplicate named users or two default user entries.

Common situations: Programmatic AclSpec construction with repeated addEntry for the same principal; merging ACLs where input already contains duplicates; copy-paste of ACL entries in tooling.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/7851411367605f2d. Report an issue: GitHub.