elastic/elasticsearch · error · IllegalArgumentException
Filter exceeds maximum depth at [${filter}]
Error message
Filter exceeds maximum depth at [${filter}] What it means
Thrown by FilterPath.FilterPathBuilder.insertNode when the depth of a filter path exceeds MAX_TREE_DEPTH (500). FilterPath is used by source filtering (`_source.includes/excludes`) and `filter_path` on REST responses. The depth check is a denial-of-service guard preventing pathological, deeply-nested filter expressions from consuming excessive memory/CPU during trie construction.
Source
Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/support/filtering/FilterPath.java:161
BuildNode(boolean isFinalNode) {
children = new HashMap<>();
this.isFinalNode = isFinalNode;
}
}
private final BuildNode root = new BuildNode(false);
void insert(String filter) {
insertNode(filter, root, 0);
}
FilterPath build() {
return buildPath("", root);
}
static void insertNode(String filter, BuildNode node, int depth) {
if (depth > MAX_TREE_DEPTH) {
throw new IllegalArgumentException(
"Filter exceeds maximum depth at [" + (filter.length() > 100 ? filter.substring(0, 100) : filter) + "]"
);
}
int end = filter.length();
int splitPosition = -1;
boolean findEscapes = false;
for (int i = 0; i < end; i++) {
char c = filter.charAt(i);
if (c == '.') {
splitPosition = i;
break;
} else if ((c == '\\') && (i + 1 < end) && (filter.charAt(i + 1) == '.')) {
++i;
findEscapes = true;
}
}
if (splitPosition > 0) {View on GitHub (pinned to db6a809a66)
Solutions
- Reduce the filter path to fewer than 500 segments; prefer wildcard patterns (`a.*.b`) over fully enumerated deep paths.
- Audit the code that builds the filter string for runaway concatenation loops.
- If you genuinely need such depth, redesign the document model to flatten nesting or use a different filtering strategy.
- Validate the filter string length/segment count client-side before sending the request.
Example fix
// before: filter_path built by unbounded loop
String path = ""; for (int i=0;i<1000;i++){ path += "a."; }
// after: cap the depth client-side
if (path.split("\\.").length > 500) throw new IllegalArgumentException("filter too deep"); Defensive patterns
Strategy: validation
Validate before calling
static void checkFilterDepth(String filter) {
if (filter.split("\\.").length > 500) {
throw new IllegalArgumentException("filter path too deep (>500 segments): " + filter);
}
} Prevention
- Cap programmatically-generated filter paths client-side.
- Prefer wildcard filter patterns over fully enumerated deep paths.
- Audit loops that concatenate filter segments.
When it happens
Trigger: Submitting a `_source` include/exclude pattern or a REST `filter_path` query parameter with more than 500 dot-separated segments (e.g. a.a.a... 501 levels deep), or an expression that the splitting logic recurses on past depth 500. Generated/programmatic filter strings can hit this when a loop concatenates path segments unbounded.
Common situations: Automated clients building filter paths from arbitrarily deep object schemas. Misconfigured tools that concatenate filter segments without bounds. A payload generator bug repeating a segment thousands of times. Trying to filter on a deeply nested document model where the path is constructed dynamically.
Related errors
- Required one of fields {}, but none were specified.
- The following fields are not allowed together: {}
- Elasticsearch version is missing from properties.
- Expected elasticsearch version to be numbers only of the for
- Invalid qualifier: ${qualifier}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/72902ec8dd5d3e05.
Report an issue: GitHub.