{"record":{"id":"11d1adf28ad2959e","repo":"elastic/elasticsearch","slug":"a-files-entitlement-entry-must-contain-one-of-pat","errorCode":null,"errorMessage":"a files entitlement entry must contain one of [path, relative_path, path_setting]","messagePattern":"a files entitlement entry must contain one of \\[path, relative_path, path_setting\\]","errorType":"validation","errorClass":"PolicyValidationException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java","lineNumber":253,"sourceCode":"        List<FileData> filesData = new ArrayList<>();\n        for (Object object : paths) {\n            Map<String, Object> file = new HashMap<>((Map<String, Object>) object);\n            String pathAsString = checkString.apply(file, \"path\");\n            String relativePathAsString = checkString.apply(file, \"relative_path\");\n            String relativeTo = checkString.apply(file, \"relative_to\");\n            String pathSetting = checkString.apply(file, \"path_setting\");\n            String settingBaseDirAsString = checkString.apply(file, \"basedir_if_relative\");\n            String modeAsString = checkString.apply(file, \"mode\");\n            String platformAsString = checkString.apply(file, \"platform\");\n            Boolean exclusiveBoolean = checkBoolean.apply(file, \"exclusive\");\n            boolean exclusive = exclusiveBoolean != null && exclusiveBoolean;\n\n            if (file.isEmpty() == false) {\n                throw new PolicyValidationException(\"unknown key(s) [\" + file + \"] in a listed file for files entitlement\");\n            }\n            int foundKeys = (pathAsString != null ? 1 : 0) + (relativePathAsString != null ? 1 : 0) + (pathSetting != null ? 1 : 0);\n            if (foundKeys != 1) {\n                throw new PolicyValidationException(\n                    \"a files entitlement entry must contain one of \" + \"[path, relative_path, path_setting]\"\n                );\n            }\n\n            if (modeAsString == null) {\n                throw new PolicyValidationException(\"files entitlement must contain 'mode' for every listed file\");\n            }\n            Mode mode = parseMode(modeAsString);\n            Platform platform = null;\n            if (platformAsString != null) {\n                platform = parsePlatform(platformAsString);\n            }\n\n            if (relativeTo != null && relativePathAsString == null) {\n                throw new PolicyValidationException(\"'relative_to' may only be used with 'relative_path'\");\n            }\n\n            if (settingBaseDirAsString != null && pathSetting == null) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java#L235-L271","documentation":"Thrown when none (or more than one) of the mutually-exclusive path-designator keys path / relative_path / path_setting is set on a files-entitlement entry. The parser counts non-null occurrences among the three and requires exactly one so each entry resolves to an unambiguous target.","triggerScenarios":"An entry omits all three path keys (e.g. only `mode` is provided), or supplies more than one (e.g. both `path` and `relative_path`). The foundKeys counter will be 0 or 2+ respectively.","commonSituations":"Forgetting the path designator entirely; providing both `path` and `relative_path` thinking they compose; templating bug that conditionally drops the path; misunderstanding that exactly one is required.","solutions":["Provide exactly one of: `path` (absolute), `relative_path` (paired with `relative_to`), or `path_setting` (paired with `basedir_if_relative`).","If two are present, decide which one you meant and delete the other.","If none is present, add the one matching your intent."],"exampleFix":"// before\n{ \"mode\": \"read\", \"path\": \"/x\", \"relative_path\": \"logs\" }\n\n// after\n{ \"mode\": \"read\", \"relative_path\": \"logs\", \"relative_to\": \"home\" }","handlingStrategy":"validation","validationCode":"public static void validateExactlyOnePathDesignator(Map<String,Object> entry) {\n    int n = 0;\n    for (String k : List.of(\"path\",\"relative_path\",\"path_setting\")) if (entry.containsKey(k)) n++;\n    if (n != 1) {\n        throw new IllegalArgumentException(\"entry must contain exactly one of path/relative_path/path_setting, got \" + n);\n    }\n}","typeGuard":"public static boolean hasExactlyOnePathDesignator(Map<String,Object> entry) {\n    int n = 0;\n    if (entry.containsKey(\"path\")) n++;\n    if (entry.containsKey(\"relative_path\")) n++;\n    if (entry.containsKey(\"path_setting\")) n++;\n    return n == 1;\n}","tryCatchPattern":null,"preventionTips":["Enforce a JSON Schema oneOf over the three path designators.","When templating, never emit an entry without a path designator.","If multiple seem relevant, pick one and delete the rest."],"tags":["entitlements","files","policy","validation","paths"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}