{"record":{"id":"37ad10764c76ac65","repo":"elastic/elasticsearch","slug":"must-specify-at-least-one-path","errorCode":null,"errorMessage":"must specify at least one path","messagePattern":"must specify at least one path","errorType":"validation","errorClass":"PolicyValidationException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java","lineNumber":199,"sourceCode":"        return switch (baseDir) {\n            case \"config\" -> BaseDir.CONFIG;\n            case \"data\" -> BaseDir.DATA;\n            case \"home\" -> BaseDir.USER_HOME;\n            case \"shared_data\" -> BaseDir.SHARED_DATA;\n            // it would be nice to limit this to just ES modules, but we don't have a way to plumb that through to here\n            // however, we still don't document in the error case below that shared_repo and shared_data is valid\n            case \"shared_repo\" -> BaseDir.SHARED_REPO;\n            default -> throw new PolicyValidationException(\n                \"invalid relative directory: \" + baseDir + \", valid values: [config, data, home]\"\n            );\n        };\n    }\n\n    @ExternalEntitlement(parameterNames = { \"paths\" }, esModulesOnly = false)\n    @SuppressWarnings(\"unchecked\")\n    public static FilesEntitlement build(List<Object> paths) {\n        if (paths == null || paths.isEmpty()) {\n            throw new PolicyValidationException(\"must specify at least one path\");\n        }\n        BiFunction<Map<String, Object>, String, String> checkString = (values, key) -> {\n            Object value = values.remove(key);\n            if (value == null) {\n                return null;\n            } else if (value instanceof String str) {\n                return str;\n            }\n            throw new PolicyValidationException(\n                \"expected [\"\n                    + key\n                    + \"] to be type [\"\n                    + String.class.getSimpleName()\n                    + \"] but found type [\"\n                    + value.getClass().getSimpleName()\n                    + \"]\"\n            );\n        };","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java#L181-L217","documentation":"Thrown at the top of FilesEntitlement.build when the `paths` argument is null or empty. A files entitlement with no path entries is meaningless — it would grant nothing — so the parser refuses to construct it rather than silently producing a no-op entitlement.","triggerScenarios":"A policy file declares a files entitlement whose `paths` array is missing, null, or empty (e.g. `\"files\": { \"paths\": [] }` or `\"files\": { \"paths\": null }`).","commonSituations":"Template/policy skeleton left in place with no entries; conditional generation of policy that yielded zero entries; misunderstanding that the entitlement requires at least one declared path; YAML/JSON merge that produced an empty list.","solutions":["Populate the `paths` array with at least one entry containing a `path`/`relative_path`/`path_setting` plus a `mode`.","If you intended to grant no file access, remove the entire `files` entitlement block from the policy instead of leaving an empty list."],"exampleFix":"// before\n\"files\": { \"paths\": [] }\n\n// after\n\"files\": {\n  \"paths\": [\n    { \"relative_path\": \"logs\", \"relative_to\": \"home\", \"mode\": \"read\" }\n  ]\n}","handlingStrategy":"validation","validationCode":"public static void validateFilesEntitlement(List<?> paths) {\n    if (paths == null || paths.isEmpty()) {\n        throw new IllegalArgumentException(\"files entitlement requires at least one path entry\");\n    }\n}","typeGuard":"public static boolean hasAtLeastOnePath(List<?> paths) {\n    return paths != null && !paths.isEmpty();\n}","tryCatchPattern":null,"preventionTips":["If you do not need file access, omit the files entitlement entirely.","In policy generators, skip the block when the entries list is empty rather than emitting it.","Add a JSON Schema minItems:1 on the paths array."],"tags":["entitlements","files","policy","validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}