{"record":{"id":"0cfcd85bbe5595b6","repo":"iOfficeAI/OfficeCLI","slug":"regex-pattern-pattern-exceeded-regexmatchtime","errorCode":null,"errorMessage":"Regex pattern '{pattern}' exceeded {RegexMatchTimeout.TotalSeconds}s match timeout (catastrophic backtracking?)","messagePattern":"Regex pattern '(.+?)' exceeded (.+?)s match timeout \\(catastrophic backtracking\\?\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/FindHelpers.cs","lineNumber":64,"sourceCode":"        if (isRegex)\n        {\n            try\n            {\n                // Bound matching with a hard timeout so catastrophic-backtracking\n                // patterns (e.g. \"(a+)+b\") fail fast instead of hanging the process.\n                foreach (Match m in Regex.Matches(fullText, pattern, RegexOptions.None, RegexMatchTimeout))\n                {\n                    if (m.Length > 0) // skip zero-length matches\n                        ranges.Add((m.Index, m.Length));\n                }\n            }\n            catch (RegexParseException ex)\n            {\n                throw new ArgumentException($\"Invalid regex pattern '{pattern}': {ex.Message}\", ex);\n            }\n            catch (RegexMatchTimeoutException ex)\n            {\n                throw new ArgumentException(\n                    $\"Regex pattern '{pattern}' exceeded {RegexMatchTimeout.TotalSeconds}s match timeout (catastrophic backtracking?)\",\n                    ex);\n            }\n        }\n        else\n        {\n            int idx = 0;\n            while ((idx = fullText.IndexOf(pattern, idx, StringComparison.Ordinal)) >= 0)\n            {\n                ranges.Add((idx, pattern.Length));\n                idx += pattern.Length;\n            }\n        }\n        return ranges;\n    }\n}\n","sourceCodeStart":46,"sourceCodeEnd":81,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/FindHelpers.cs#L46-L81","documentation":"Thrown by FindHelpers when a regex match exceeds the 5-second timeout (FindHelpers.RegexMatchTimeout). The bound exists specifically to stop catastrophic-backtracking patterns (e.g. '(a+)+b') from hanging the process; the timeout is rewrapped as an ArgumentException naming the pattern.","triggerScenarios":"Calling a find/search API with a regex that takes longer than 5 seconds to match against the target text. Patterns with nested quantifiers or overlapping alternatives on long inputs are the usual cause.","commonSituations":"An evil/inefficient pattern on large document text; user-supplied regex not vetted for performance; a pattern that performs well on short input but blows up on production-size text.","solutions":["Rewrite the pattern to avoid catastrophic backtracking (eliminate nested quantifiers, use atomic/possessive constructs or anchoring).","Narrow the search scope (search a specific sheet/region) to reduce input size.","Pre-validate user-supplied regex against representative input with a local timeout before using it."],"exampleFix":"// before\nFind(sheet, pattern: \"(a+)+b\", useRegex: true); // catastrophic\n// after\nFind(sheet, pattern: \"a+b\", useRegex: true); // linear","handlingStrategy":"try-catch","validationCode":"static bool MatchesWithinTimeout(string text, string pattern, TimeSpan timeout)\n{ try { return Regex.IsMatch(text, pattern, RegexOptions.None, timeout); } catch (RegexMatchTimeoutException) { return false; } }","typeGuard":null,"tryCatchPattern":"try { Find(sheet, pattern, useRegex: true); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"match timeout\"))\n{ /* simplify the pattern or narrow scope */ }","preventionTips":["Avoid nested quantifiers like (a+)+ in user patterns.","Test regex on representative-size input with a local timeout."],"tags":["find","regex","timeout","performance"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}