elastic/elasticsearch · error · PolicyValidationException

must specify at least one path

Error message

must specify at least one path

What it means

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.

Source

Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java:199

        return switch (baseDir) {
            case "config" -> BaseDir.CONFIG;
            case "data" -> BaseDir.DATA;
            case "home" -> BaseDir.USER_HOME;
            case "shared_data" -> BaseDir.SHARED_DATA;
            // it would be nice to limit this to just ES modules, but we don't have a way to plumb that through to here
            // however, we still don't document in the error case below that shared_repo and shared_data is valid
            case "shared_repo" -> BaseDir.SHARED_REPO;
            default -> throw new PolicyValidationException(
                "invalid relative directory: " + baseDir + ", valid values: [config, data, home]"
            );
        };
    }

    @ExternalEntitlement(parameterNames = { "paths" }, esModulesOnly = false)
    @SuppressWarnings("unchecked")
    public static FilesEntitlement build(List<Object> paths) {
        if (paths == null || paths.isEmpty()) {
            throw new PolicyValidationException("must specify at least one path");
        }
        BiFunction<Map<String, Object>, String, String> checkString = (values, key) -> {
            Object value = values.remove(key);
            if (value == null) {
                return null;
            } else if (value instanceof String str) {
                return str;
            }
            throw new PolicyValidationException(
                "expected ["
                    + key
                    + "] to be type ["
                    + String.class.getSimpleName()
                    + "] but found type ["
                    + value.getClass().getSimpleName()
                    + "]"
            );
        };

View on GitHub (pinned to db6a809a66)

Solutions

  1. Populate the `paths` array with at least one entry containing a `path`/`relative_path`/`path_setting` plus a `mode`.
  2. If you intended to grant no file access, remove the entire `files` entitlement block from the policy instead of leaving an empty list.

Example fix

// before
"files": { "paths": [] }

// after
"files": {
  "paths": [
    { "relative_path": "logs", "relative_to": "home", "mode": "read" }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

public static void validateFilesEntitlement(List<?> paths) {
    if (paths == null || paths.isEmpty()) {
        throw new IllegalArgumentException("files entitlement requires at least one path entry");
    }
}

Type guard

public static boolean hasAtLeastOnePath(List<?> paths) {
    return paths != null && !paths.isEmpty();
}

Prevention

When it happens

Trigger: A policy file declares a files entitlement whose `paths` array is missing, null, or empty (e.g. `"files": { "paths": [] }` or `"files": { "paths": null }`).

Common situations: 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.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/37ad10764c76ac65. Report an issue: GitHub.