{"record":{"id":"13777f0019e63beb","repo":"elastic/elasticsearch","slug":"using-module-found-duplicate-entitlement","errorCode":null,"errorMessage":"[{}] using module [{}] found duplicate entitlement [{}]","messagePattern":"\\[(.+?)\\] using module \\[(.+?)\\] found duplicate entitlement \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java","lineNumber":293,"sourceCode":"        FileAccessTree.validateExclusivePaths(exclusivePaths, FileAccessTree.DEFAULT_COMPARISON);\n        this.exclusivePaths = exclusivePaths;\n        this.forbiddenPaths = createForbiddenPaths(pathLookup);\n    }\n\n    private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy policy) {\n        return policy.scopes().stream().collect(toUnmodifiableMap(Scope::moduleName, Scope::entitlements));\n    }\n\n    private static void validateEntitlementsPerModule(\n        String componentName,\n        String moduleName,\n        List<Entitlement> entitlements,\n        List<ExclusiveFileEntitlement> exclusiveFileEntitlements\n    ) {\n        Set<Class<? extends Entitlement>> found = new HashSet<>();\n        for (var e : entitlements) {\n            if (found.contains(e.getClass())) {\n                throw new IllegalArgumentException(\n                    \"[\" + componentName + \"] using module [\" + moduleName + \"] found duplicate entitlement [\" + e.getClass().getName() + \"]\"\n                );\n            }\n            found.add(e.getClass());\n            if (e instanceof FilesEntitlement fe) {\n                exclusiveFileEntitlements.add(new ExclusiveFileEntitlement(componentName, moduleName, fe));\n            }\n        }\n    }\n\n    protected ModuleEntitlements getEntitlements(Class<?> requestingClass) {\n        return moduleEntitlementsMap.computeIfAbsent(requestingClass.getModule(), m -> computeEntitlements(requestingClass));\n    }\n\n    protected final ModuleEntitlements computeEntitlements(Class<?> requestingClass) {\n        var policyScope = scopeResolver.apply(requestingClass);\n        var componentName = policyScope.componentName();\n        var moduleName = policyScope.moduleName();","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java#L275-L311","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmodule: org.elasticsearch.foo\nentitlements:\n  - files: [{ path: /a }]\n  - files: [{ path: /b }]\n\n// after: one files entitlement\nmodule: org.elasticsearch.foo\nentitlements:\n  - files: [{ path: /a }, { path: /b }]","handlingStrategy":"validation","validationCode":"// Pre-validate: each entitlement type appears once per module\nMap<String, Set<Class<?>>> seen = new HashMap<>();\nfor (var e : moduleEntitlements) {\n  var set = seen.computeIfAbsent(moduleName, k -> new HashSet<>());\n  if (!set.add(e.getClass())) {\n    throw new IllegalArgumentException(\"duplicate \" + e.getClass().getSimpleName() + \" in \" + moduleName);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["entitlement","policy","duplicate","validation"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}