{"record":{"id":"72902ec8dd5d3e05","repo":"elastic/elasticsearch","slug":"filter-exceeds-maximum-depth-at-filter","errorCode":null,"errorMessage":"Filter exceeds maximum depth at [${filter}]","messagePattern":"Filter exceeds maximum depth at \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/x-content/src/main/java/org/elasticsearch/xcontent/support/filtering/FilterPath.java","lineNumber":161,"sourceCode":"            BuildNode(boolean isFinalNode) {\n                children = new HashMap<>();\n                this.isFinalNode = isFinalNode;\n            }\n        }\n\n        private final BuildNode root = new BuildNode(false);\n\n        void insert(String filter) {\n            insertNode(filter, root, 0);\n        }\n\n        FilterPath build() {\n            return buildPath(\"\", root);\n        }\n\n        static void insertNode(String filter, BuildNode node, int depth) {\n            if (depth > MAX_TREE_DEPTH) {\n                throw new IllegalArgumentException(\n                    \"Filter exceeds maximum depth at [\" + (filter.length() > 100 ? filter.substring(0, 100) : filter) + \"]\"\n                );\n            }\n            int end = filter.length();\n            int splitPosition = -1;\n            boolean findEscapes = false;\n            for (int i = 0; i < end; i++) {\n                char c = filter.charAt(i);\n                if (c == '.') {\n                    splitPosition = i;\n                    break;\n                } else if ((c == '\\\\') && (i + 1 < end) && (filter.charAt(i + 1) == '.')) {\n                    ++i;\n                    findEscapes = true;\n                }\n            }\n\n            if (splitPosition > 0) {","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/filtering/FilterPath.java#L143-L179","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: filter_path built by unbounded loop\nString path = \"\"; for (int i=0;i<1000;i++){ path += \"a.\"; }\n// after: cap the depth client-side\nif (path.split(\"\\\\.\").length > 500) throw new IllegalArgumentException(\"filter too deep\");","handlingStrategy":"validation","validationCode":"static void checkFilterDepth(String filter) {\n  if (filter.split(\"\\\\.\").length > 500) {\n    throw new IllegalArgumentException(\"filter path too deep (>500 segments): \" + filter);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Cap programmatically-generated filter paths client-side.","Prefer wildcard filter patterns over fully enumerated deep paths.","Audit loops that concatenate filter segments."],"tags":["xcontent","filtering","source-filtering","dos-protection","validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}