elastic/elasticsearch · error · PolicyValidationException

expected [{}] to be type [String] but found type [{}]

Error message

expected [{}] to be type [String] but found type [{}]

What it means

Thrown by the checkString helper in FilesEntitlement.build when one of the string-typed fields (path, relative_path, relative_to, path_setting, basedir_if_relative, mode, platform) is present in the entry map but its value is not a JSON string — e.g. a number, boolean, list, or object.

Source

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

                "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()
                    + "]"
            );
        };
        BiFunction<Map<String, Object>, String, Boolean> checkBoolean = (values, key) -> {
            Object value = values.remove(key);
            if (value == null) {
                return null;
            } else if (value instanceof Boolean bool) {
                return bool;
            }
            throw new PolicyValidationException(
                "expected ["

View on GitHub (pinned to db6a809a66)

Solutions

  1. Read the message: it names the field (`key`) and the actual type found.
  2. Quote the value so it is a JSON string.
  3. Re-validate the policy JSON with a linter before encoding.

Example fix

// before
{ "path": /var/log/es, "mode": read_write }

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

Strategy: type-guard

Validate before calling

private static final Set<String> STRING_KEYS = Set.of(
    "path","relative_path","relative_to","path_setting","basedir_if_relative","mode","platform");
public static void validateStringFields(Map<String,Object> entry) {
    for (String k : STRING_KEYS) {
        Object v = entry.get(k);
        if (v != null && !(v instanceof String)) {
            throw new IllegalArgumentException(k + " must be a string, got " + v.getClass().getSimpleName());
        }
    }
}

Type guard

public static boolean allStringFieldsAreStrings(Map<String,Object> entry) {
    for (String k : Set.of("path","relative_path","relative_to","path_setting","basedir_if_relative","mode","platform")) {
        Object v = entry.get(k);
        if (v != null && !(v instanceof String)) return false;
    }
    return true;
}

Prevention

When it happens

Trigger: A files-entitlement entry sets one of the string fields to a non-string JSON value, for example `{ "path": 42 }`, `{ "mode": true }`, or `{ "relative_path": ["a","b"] }`.

Common situations: Quoting mistake in hand-written JSON (writing `mode: read_write` instead of `"mode": "read_write"`); YAML-to-JSON conversion where a bare token became a non-string scalar; numeric path id used instead of string; booleans for non-boolean fields.

Related errors


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