elastic/elasticsearch · error · IllegalArgumentException
[{}] using module [{}] found duplicate entitlement [{}]
Error message
[{}] using module [{}] found duplicate entitlement [{}] What it means
Thrown by PolicyManager.validateEntitlementsPerModule when the same entitlement class (e.g. FilesEntitlement, OutboundNetworkEntitlement) appears more than once within a single module's entitlement list for a component. Each module may declare each entitlement type at most once; duplicates are rejected as they would create ambiguous policy.
Source
Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java:293
FileAccessTree.validateExclusivePaths(exclusivePaths, FileAccessTree.DEFAULT_COMPARISON);
this.exclusivePaths = exclusivePaths;
this.forbiddenPaths = createForbiddenPaths(pathLookup);
}
private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy policy) {
return policy.scopes().stream().collect(toUnmodifiableMap(Scope::moduleName, Scope::entitlements));
}
private static void validateEntitlementsPerModule(
String componentName,
String moduleName,
List<Entitlement> entitlements,
List<ExclusiveFileEntitlement> exclusiveFileEntitlements
) {
Set<Class<? extends Entitlement>> found = new HashSet<>();
for (var e : entitlements) {
if (found.contains(e.getClass())) {
throw new IllegalArgumentException(
"[" + componentName + "] using module [" + moduleName + "] found duplicate entitlement [" + e.getClass().getName() + "]"
);
}
found.add(e.getClass());
if (e instanceof FilesEntitlement fe) {
exclusiveFileEntitlements.add(new ExclusiveFileEntitlement(componentName, moduleName, fe));
}
}
}
protected ModuleEntitlements getEntitlements(Class<?> requestingClass) {
return moduleEntitlementsMap.computeIfAbsent(requestingClass.getModule(), m -> computeEntitlements(requestingClass));
}
protected final ModuleEntitlements computeEntitlements(Class<?> requestingClass) {
var policyScope = scopeResolver.apply(requestingClass);
var componentName = policyScope.componentName();
var moduleName = policyScope.moduleName();View on GitHub (pinned to db6a809a66)
Solutions
- Open the named component's policy file and find the duplicate entitlement block under the named module.
- Merge the two duplicate entries into a single entitlement of that type (e.g. combine the two 'files' lists).
- Remove the redundant entry.
Example fix
// before
module: org.elasticsearch.foo
entitlements:
- files: [{ path: /a }]
- files: [{ path: /b }]
// after: one files entitlement
module: org.elasticsearch.foo
entitlements:
- files: [{ path: /a }, { path: /b }] Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate: each entitlement type appears once per module
Map<String, Set<Class<?>>> seen = new HashMap<>();
for (var e : moduleEntitlements) {
var set = seen.computeIfAbsent(moduleName, k -> new HashSet<>());
if (!set.add(e.getClass())) {
throw new IllegalArgumentException("duplicate " + e.getClass().getSimpleName() + " in " + moduleName);
}
} Prevention
- Lint policy YAML for repeated keys of the same entitlement type per module.
- Merge multiple entries of the same type into one during policy authoring.
When it happens
Trigger: Iterating a module's entitlements, the 'found' set already contains e.getClass() when the same class is encountered a second time. The message names the component, the module, and the duplicated entitlement class.
Common situations: A policy YAML lists two 'files:' blocks under the same module; copy-paste added a second 'outbound_network:' under one module; merging policy fragments without de-duplicating.
Related errors
- Error occurred when inspecting class: {}; SerializedLambda r
- Error occurred when inspecting class: {}
- Proxy fallback only supports instance method references; no
- Method reference passed to 'calling()' does not belong to {}
- No constructor found on {} with parameter types {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/13777f0019e63beb.
Report an issue: GitHub.