{"record":{"id":"914050d58b9b645c","repo":"elastic/elasticsearch","slug":"can-not-convert-grok-patterns-to-regular-expressio","errorCode":null,"errorMessage":"Can not convert grok patterns to regular expression","messagePattern":"Can not convert grok patterns to regular expression","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/grok/src/main/java/org/elasticsearch/grok/Grok.java","lineNumber":171,"sourceCode":"            String grokPart;\n            if (namedCaptures && subName != null) {\n                grokPart = String.format(Locale.US, \"(?<%s>%s)\", namedPatternRef, pattern);\n            } else if (namedCaptures) {\n                grokPart = String.format(Locale.US, \"(?:%s)\", pattern);\n            } else {\n                grokPart = String.format(Locale.US, \"(?<%s>%s)\", patternName + \"_\" + result, pattern);\n            }\n            String start = new String(grokPatternBytes, 0, result, StandardCharsets.UTF_8);\n            String rest = new String(\n                grokPatternBytes,\n                region.getEnd(0),\n                grokPatternBytes.length - region.getEnd(0),\n                StandardCharsets.UTF_8\n            );\n            grokPattern = grokPart + rest;\n            res.append(start);\n        }\n        throw new IllegalArgumentException(\"Can not convert grok patterns to regular expression\");\n    }\n\n    /**\n     * Checks whether a specific text matches the defined grok expression.\n     *\n     * @param text the string to match\n     * @return true if grok expression matches text or there is a timeout, false otherwise.\n     */\n    public boolean match(String text) {\n        Matcher matcher = compiledExpression.matcher(text.getBytes(StandardCharsets.UTF_8));\n        int result;\n        try {\n            matcherWatchdog.register(matcher);\n            result = matcher.search(0, text.length(), Option.DEFAULT);\n        } finally {\n            matcherWatchdog.unregister(matcher);\n        }\n        handleInterrupted(result);","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/grok/src/main/java/org/elasticsearch/grok/Grok.java#L153-L189","documentation":"Thrown by Grok.toRegex() when the pattern expansion loop exceeds MAX_TO_REGEX_ITERATIONS (100,000 iterations) without converging to a fully-expanded regex. Each iteration resolves one %{PATTERN} reference. This is a safety valve against pathological patterns that expand exponentially or have indirect circular references (A→B→A) that are not caught by the direct self-reference check.","triggerScenarios":"Constructing a Grok object with a pattern that causes extremely deep or non-terminating expansion. This can happen with: indirect circular references (A references B, B references A — the direct check only catches A→A); deeply nested pattern chains; patterns that expand to extremely large regexes through combinatorial expansion.","commonSituations":"Custom grok pattern with indirect circular references (not caught by the direct self-reference check); importing a large external pattern set with complex interdependencies that create exponential expansion; a pattern chain that is legitimately very deep (exceeding 100K references).","solutions":["Check for indirect circular references in custom pattern definitions (A→B→A patterns).","Simplify the grok pattern to reduce the depth of pattern nesting.","Flatten frequently-referenced patterns inline to reduce expansion depth.","Audit custom pattern files for chains where patterns reference each other in a cycle."],"exampleFix":"// before — indirect circular reference\n// A %{B}\n// B %{A}\n\n// after — break the cycle\n// A \\d+\n// B %{A}","handlingStrategy":"validation","validationCode":"// Detect indirect circular references by building a dependency graph\nMap<String, Set<String>> deps = buildPatternDependencyGraph(patternBank);\nfor (String pattern : deps.keySet()) {\n    if (hasCycle(pattern, deps, new HashSet<>())) {\n        throw new IllegalArgumentException(\"Indirect circular reference detected involving pattern: \" + pattern);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    new Grok(bank, pattern, callback);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Can not convert\")) {\n        // pattern expansion too deep — check for indirect cycles or simplify nesting\n    }\n    throw e;\n}","preventionTips":["Audit custom pattern files for indirect circular references (A→B→A).","Limit pattern nesting depth to avoid hitting the 100K iteration limit.","Flatten frequently-referenced patterns inline where possible."],"tags":["grok","pattern-matching","validation","circular-reference","iteration-limit","ingest"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}