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
- Read the message: it names the field (`key`) and the actual type found.
- Quote the value so it is a JSON string.
- 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
- Always quote string literals in policy JSON.
- Use a JSON Schema with `type: string` on each string field.
- When generating from YAML/JSON, ensure serializers emit strings, not bare scalars.
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
- expected [{}] to be type [boolean] but found type [{}]
- invalid mode: {}, valid values: [read, read_write]
- invalid platform: {}, valid values: [linux, macos, windows]
- invalid relative directory: {}, valid values: [config, data,
- must specify at least one path
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/02080b5ec2d40c5b.
Report an issue: GitHub.