elastic/elasticsearch · error · PolicyValidationException

unknown key(s) [ ] in a listed file for files entitlement

Error message

unknown key(s) [{}] in a listed file for files entitlement

What it means

Thrown after FilesEntitlement.build has consumed all known keys from the entry map (path, relative_path, relative_to, path_setting, basedir_if_relative, mode, platform, exclusive). If the map still has leftover keys, those are unrecognised and the policy is rejected to surface typos and stale field names rather than silently ignoring them.

Solutions

  1. Read the message: it prints the leftover key map verbatim, naming the unknown keys.
  2. Rename or remove each unknown key; map it to the closest recognised equivalent (e.g. `readonly:true` -> `mode: "read"`).
  3. Validate the policy against the current schema before deploying.

Example fix

// before
{ "dir": "/var/log/es", "access": "rw" }

// after
{ "path": "/var/log/es", "mode": "read_write" }
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> ALLOWED_KEYS = Set.of(
    "path","relative_path","relative_to","path_setting","basedir_if_relative","mode","platform","exclusive");
public static void validateEntryKeys(Map<String,Object> entry) {
    for (String k : entry.keySet()) {
        if (!ALLOWED_KEYS.contains(k)) {
            throw new IllegalArgumentException("unknown key in files entry: " + k);
        }
    }
}

Type guard

public static boolean hasOnlyAllowedKeys(Map<String,Object> entry) {
    return ALLOWED_KEYS.containsAll(entry.keySet());
}

Prevention

When it happens

Trigger: A files-entitlement entry contains any key other than the eight recognised ones, e.g. `dir`, `target`, `access`, `recursive`, `readonly`, or a misspelling like `relativ_path`.

Common situations: Misspelling a field; using a field name from a different entitlement schema or older/newer version; copy-paste from documentation that uses an alias the parser does not accept; trailing scaffold keys from templating.

Related errors


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

Appendix: source

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

                    + value.getClass().getSimpleName()
                    + "]"
            );
        };
        List<FileData> filesData = new ArrayList<>();
        for (Object object : paths) {
            Map<String, Object> file = new HashMap<>((Map<String, Object>) object);
            String pathAsString = checkString.apply(file, "path");
            String relativePathAsString = checkString.apply(file, "relative_path");
            String relativeTo = checkString.apply(file, "relative_to");
            String pathSetting = checkString.apply(file, "path_setting");
            String settingBaseDirAsString = checkString.apply(file, "basedir_if_relative");
            String modeAsString = checkString.apply(file, "mode");
            String platformAsString = checkString.apply(file, "platform");
            Boolean exclusiveBoolean = checkBoolean.apply(file, "exclusive");
            boolean exclusive = exclusiveBoolean != null && exclusiveBoolean;

            if (file.isEmpty() == false) {
                throw new PolicyValidationException("unknown key(s) [" + file + "] in a listed file for files entitlement");
            }
            int foundKeys = (pathAsString != null ? 1 : 0) + (relativePathAsString != null ? 1 : 0) + (pathSetting != null ? 1 : 0);
            if (foundKeys != 1) {
                throw new PolicyValidationException(
                    "a files entitlement entry must contain one of " + "[path, relative_path, path_setting]"
                );
            }

            if (modeAsString == null) {
                throw new PolicyValidationException("files entitlement must contain 'mode' for every listed file");
            }
            Mode mode = parseMode(modeAsString);
            Platform platform = null;
            if (platformAsString != null) {
                platform = parsePlatform(platformAsString);
            }

            if (relativeTo != null && relativePathAsString == null) {

View on GitHub (pinned to db6a809a66)