elastic/elasticsearch · error · IllegalArgumentException

duplicate/overlapping exclusive paths found in files entitle

Error message

duplicate/overlapping exclusive paths found in files entitlements: {} and {}

What it means

Thrown by FileAccessTree.validateExclusivePaths when two exclusive paths are identical or one is a parent (ancestor) of another within the same sorted list. Even if the components are the same, nested or duplicated exclusive paths create ambiguity and are rejected. The check uses the comparison's path comparator and isParent/samePath predicates, so it is platform-aware (separator, case).

Source

Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java:168

                                    + "]"
                            );
                        }
                        exclusivePath.moduleNames.add(efe.moduleName());
                    }
                }
            }
        }
        return exclusivePaths.values().stream().sorted(comparing(ExclusivePath::path, comparison.pathComparator())).distinct().toList();
    }

    static void validateExclusivePaths(List<ExclusivePath> exclusivePaths, FileAccessTreeComparison comparison) {
        if (exclusivePaths.isEmpty() == false) {
            ExclusivePath currentExclusivePath = exclusivePaths.get(0);
            for (int i = 1; i < exclusivePaths.size(); ++i) {
                ExclusivePath nextPath = exclusivePaths.get(i);
                if (comparison.samePath(currentExclusivePath.path(), nextPath.path)
                    || comparison.isParent(currentExclusivePath.path(), nextPath.path())) {
                    throw new IllegalArgumentException(
                        "duplicate/overlapping exclusive paths found in files entitlements: " + currentExclusivePath + " and " + nextPath
                    );
                }
                currentExclusivePath = nextPath;
            }
        }
    }

    @SuppressForbidden(reason = "we need the separator as a char, not a string")
    static char separatorChar() {
        return File.separatorChar;
    }

    private static final Logger logger = LogManager.getLogger(FileAccessTree.class);
    private static final String FILE_SEPARATOR = getDefaultFileSystem().getSeparator();
    static final FileAccessTreeComparison DEFAULT_COMPARISON = Platform.LINUX.isCurrent()
        ? new CaseSensitiveComparison(separatorChar())
        : new CaseInsensitiveComparison(separatorChar());

View on GitHub (pinned to db6a809a66)

Solutions

  1. Merge the nested exclusive paths into the single broadest (parent) entry.
  2. Remove the duplicate sub-path entry from the policy.
  3. Run the paths through a normalizer and de-duplicate before declaring them exclusive.

Example fix

// before
files:
  - { path: /var/lib/es/data, exclusive: true }
  - { path: /var/lib/es/data/sub, exclusive: true }

// after: keep only the parent
files:
  - { path: /var/lib/es/data, exclusive: true }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate: no exclusive path is a parent of another
List<Path> sorted = paths.stream().sorted().toList();
for (int i = 1; i < sorted.size(); i++) {
  if (sorted.get(i).startsWith(sorted.get(i - 1))) {
    throw new IllegalArgumentException("overlapping exclusive paths: " + sorted.get(i-1) + " >= " + sorted.get(i));
  }
}

Prevention

When it happens

Trigger: After sorting exclusive paths, the loop finds a pair where comparison.samePath(prev, next) or comparison.isParent(prev, next) is true. Happens when a policy lists both a directory and a subdirectory as exclusive, or lists the same path twice.

Common situations: A policy YAML lists '/data' and '/data/logs' both as exclusive; copy-paste duplication of a path entry; relative vs absolute forms of the same path both present; Windows backslash vs forward-slash normalization edge cases.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/f54c74fb8c080c91. Report an issue: GitHub.