{"record":{"id":"afad5ad75e63d426","repo":"elastic/elasticsearch","slug":"grok-pattern-matching-was-interrupted-after-m","errorCode":null,"errorMessage":"grok pattern matching was interrupted after [{}] ms","messagePattern":"grok pattern matching was interrupted after \\[(.+?)\\] ms","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"warning","filePath":"libs/grok/src/main/java/org/elasticsearch/grok/Grok.java","lineNumber":264,"sourceCode":"        }\n        extracter.extract(utf8Bytes, offset, matcher.getEagerRegion());\n        return true;\n    }\n\n    /**\n     * The list of values that this {@linkplain Grok} can capture.\n     */\n    public List<GrokCaptureConfig> captureConfig() {\n        return captureConfig;\n    }\n\n    public Regex getCompiledExpression() {\n        return compiledExpression;\n    }\n\n    private void handleInterrupted(int result) {\n        if (result == Matcher.INTERRUPTED) {\n            throw new RuntimeException(\n                \"grok pattern matching was interrupted after [\" + matcherWatchdog.maxExecutionTimeInMillis() + \"] ms\"\n            );\n        }\n    }\n\n    public static String combinePatterns(List<String> patterns) {\n        return combinePatterns(patterns, null);\n    }\n\n    public static String combinePatterns(List<String> patterns, String traceMatchKey) {\n        String combinedPattern;\n        if (patterns.size() > 1) {\n            combinedPattern = \"\";\n            for (int i = 0; i < patterns.size(); i++) {\n                String pattern = patterns.get(i);\n                String valueWrap;\n                if (traceMatchKey != null) {\n                    valueWrap = \"(?<\" + traceMatchKey + \".\" + i + \">\" + pattern + \")\";","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/grok/src/main/java/org/elasticsearch/grok/Grok.java#L246-L282","documentation":"Thrown by Grok.handleInterrupted() when the joni Matcher returns Matcher.INTERRUPTED, meaning the MatcherWatchdog interrupted the regex matching operation after exceeding its configured maximum execution time. This prevents ReDoS (Regular Expression Denial of Service) attacks where catastrophic backtracking in complex grok patterns causes matching to hang. The exception is a RuntimeException (unchecked).","triggerScenarios":"Calling Grok.match(text), Grok.captures(text), or Grok.match(bytes, offset, length, extracter) with input text that triggers catastrophic backtracking in the compiled regex, exceeding the MatcherWatchdog's maxExecutionTimeInMillis. The watchdog is registered/unregistered around each matcher.search() call.","commonSituations":"Processing log lines with a grok pattern that has nested quantifiers or ambiguous alternations causing exponential backtracking on certain inputs; a sudden increase in log message length or format complexity; running with a very low watchdog timeout; processing adversarial or malformed input designed to trigger ReDoS.","solutions":["Increase the MatcherWatchdog timeout (matcherWatchdog.maxExecutionTimeInMillis) if the input legitimately requires more matching time.","Optimize the grok pattern to avoid catastrophic backtracking — anchor patterns, reduce ambiguous alternations, use possessive quantifiers if supported.","Pre-filter or truncate input text before applying grok matching if inputs can be extremely long.","Use MatcherWatchdog.noop() only in controlled environments where ReDoS is not a concern."],"exampleFix":"// before — default or very short watchdog timeout\nnew Grok(bank, pattern, MatcherWatchdog.newInstance(100L), callback);\n\n// after — increase timeout for complex patterns\nnew Grok(bank, pattern, MatcherWatchdog.newInstance(5000L), callback);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    boolean matched = grok.match(text);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"interrupted after\")) {\n        // log and handle timeout — skip or truncate input\n        logger.warn(\"Grok matching timed out for input of length \" + text.length());\n    }\n    throw e;\n}","preventionTips":["Set an appropriate MatcherWatchdog timeout based on expected input complexity.","Optimize grok patterns to avoid catastrophic backtracking — anchor patterns, reduce ambiguous alternations.","Pre-filter or truncate very long input lines before grok processing.","Monitor grok processor timeout metrics in production."],"tags":["grok","pattern-matching","timeout","watchdog","redos","ingest"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}