{"record":{"id":"681747d5e937d12c","repo":"elastic/elasticsearch","slug":"path-is-already-exclusive-to-cannot-a","errorCode":null,"errorMessage":"Path [{}] is already exclusive to [{}]{}, cannot add exclusive access for [{}][{}]","messagePattern":"Path \\[(.+?)\\] is already exclusive to \\[(.+?)\\](.+?), cannot add exclusive access for \\[(.+?)\\]\\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java","lineNumber":139,"sourceCode":"\n    static List<ExclusivePath> buildExclusivePathList(\n        List<ExclusiveFileEntitlement> exclusiveFileEntitlements,\n        PathLookup pathLookup,\n        FileAccessTreeComparison comparison\n    ) {\n        Map<String, ExclusivePath> exclusivePaths = new HashMap<>();\n        for (ExclusiveFileEntitlement efe : exclusiveFileEntitlements) {\n            for (FilesEntitlement.FileData fd : efe.filesEntitlement().filesData()) {\n                if (fd.exclusive()) {\n                    List<Path> paths = fd.resolvePaths(pathLookup).toList();\n                    for (Path path : paths) {\n                        String normalizedPath = normalizePath(path);\n                        var exclusivePath = exclusivePaths.computeIfAbsent(\n                            normalizedPath,\n                            k -> new ExclusivePath(efe.componentName(), new HashSet<>(), normalizedPath)\n                        );\n                        if (exclusivePath.componentName().equals(efe.componentName()) == false) {\n                            throw new IllegalArgumentException(\n                                \"Path [\"\n                                    + normalizedPath\n                                    + \"] is already exclusive to [\"\n                                    + exclusivePath.componentName()\n                                    + \"]\"\n                                    + exclusivePath.moduleNames\n                                    + \", cannot add exclusive access for [\"\n                                    + efe.componentName()\n                                    + \"][\"\n                                    + efe.moduleName\n                                    + \"]\"\n                            );\n                        }\n                        exclusivePath.moduleNames.add(efe.moduleName());\n                    }\n                }\n            }\n        }","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java#L121-L157","documentation":"Thrown by FileAccessTree.buildExclusivePathList when two different components both claim exclusive access to the same normalized path. An exclusive files-entitlement reserves a path for one component (and its modules); a second component trying to register the same path as exclusive is rejected. The message names both components, the existing module set, and the conflicting module.","triggerScenarios":"Two ExclusiveFileEntitlement entries from different componentName values resolve to the same normalized path with exclusive=true. computeIfAbsent records the first component; when the second component's path matches and the componentNames differ, the IllegalArgumentException fires.","commonSituations":"Two plugins each declare exclusive access to the same directory in their policy YAML; a server policy and a plugin policy both claim a data dir exclusively; path normalization (relative vs absolute, symlinks) makes two different-looking paths collide.","solutions":["Audit the policy files for the two named components and remove or relocate the duplicate exclusive path claim.","Assign the path to exactly one component; have the other use non-exclusive access if it genuinely needs shared read.","Resolve symlinks/relative paths so each component points at a distinct directory.","If both components legitimately share the dir, mark only one as exclusive."],"exampleFix":"// before: two policies both claim /var/lib/es/data exclusively\nserver: { files: [{ path: /var/lib/es/data, exclusive: true }] }\npluginA: { files: [{ path: /var/lib/es/data, exclusive: true }] }\n\n// after: only one exclusive claim\npluginA: { files: [{ path: /var/lib/es/pluginA-data, exclusive: true }] }","handlingStrategy":"validation","validationCode":"// Pre-validate that no two components claim the same exclusive path\nMap<String, String> owner = new HashMap<>();\nfor (var c : components) {\n  for (Path p : c.exclusivePaths()) {\n    String n = normalize(p);\n    if (owner.containsKey(n) && !owner.get(n).equals(c.name())) {\n      throw new IllegalArgumentException(n + \" already exclusive to \" + owner.get(n));\n    }\n    owner.putIfAbsent(n, c.name());\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize exclusive-path allocation so two teams cannot claim the same dir.","Resolve symlinks before declaring a path exclusive."],"tags":["entitlement","files","exclusive-access","policy","conflict"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}