{"record":{"id":"88e6bd64524fdf79","repo":"charmbracelet/crush","slug":"invalid-regex-pattern-w","errorCode":null,"errorMessage":"invalid regex pattern: %w","messagePattern":"invalid regex pattern: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/grep.go","lineNumber":293,"sourceCode":"\t\t\tText string `json:\"text\"`\n\t\t} `json:\"path\"`\n\t\tLines struct {\n\t\t\tText string `json:\"text\"`\n\t\t} `json:\"lines\"`\n\t\tLineNumber int `json:\"line_number\"`\n\t\tSubmatches []struct {\n\t\t\tStart int `json:\"start\"`\n\t\t} `json:\"submatches\"`\n\t} `json:\"data\"`\n}\n\nfunc searchFilesWithRegex(pattern, rootPath, include string) ([]grepMatch, error) {\n\tmatches := []grepMatch{}\n\n\t// Use cached regex compilation\n\tregex, err := searchRegexCache.get(pattern)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid regex pattern: %w\", err)\n\t}\n\n\tvar includePattern *regexp.Regexp\n\tif include != \"\" {\n\t\tregexPattern := globToRegex(include)\n\t\tincludePattern, err = globRegexCache.get(regexPattern)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid include pattern: %w\", err)\n\t\t}\n\t}\n\n\t// Create walker with gitignore and crushignore support\n\twalker := fsext.NewFastGlobWalker(rootPath)\n\n\terr = filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn nil // Skip errors\n\t\t}","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/grep.go#L275-L311","documentation":"The grep tool compiles the user-supplied search pattern through a regex cache before walking files. When Go's regexp package cannot compile the pattern, the compile error is wrapped as 'invalid regex pattern'. This prevents an invalid pattern from aborting the file walker mid-run.","triggerScenarios":"Calling the grep tool (via searchFiles) with a pattern that is not valid Go regexp syntax, e.g. unbalanced parentheses, a trailing backslash, or an invalid character class like '[a-'.","commonSituations":"Users typing shell-glob-style patterns ('*.go') instead of regex, copying PCRE-only syntax like lookaheads '(?=...)' which Go's RE2 engine does not support, or a model-generated pattern with unescaped special characters.","solutions":["Fix the regex syntax: check for unbalanced parens/brackets and escape metacharacters with \\\\.","Validate the pattern first with regexp.Compile in a test or REPL before running the search.","Replace RE2-unsupported constructs (lookaheads/lookbehinds/backreferences) with supported equivalents.","If the pattern came from untrusted input, wrap it with regexp.QuoteMeta to treat it literally."],"exampleFix":"// before\nsearchFilesWithRegex(\"foo(?=bar)\", root, \"\")\n// after\nsearchFilesWithRegex(\"foobar\", root, \"\") // or use a two-pass search instead of lookahead","handlingStrategy":"validation","validationCode":"if _, err := regexp.Compile(pattern); err != nil {\n    return fmt.Errorf(\"bad pattern %q: %w\", pattern, err)\n}","typeGuard":"func isValidRegex(p string) bool { _, err := regexp.Compile(p); return err == nil }","tryCatchPattern":"if err != nil {\n    var re *regexp.SyntaxError\n    if errors.As(err, &re) { /* surface syntax position */ }\n}","preventionTips":["Prefer literal searches (QuoteMeta) when patterns come from user input","Test patterns against regexp.Compile before use","Avoid PCRE features unsupported by Go's RE2"],"tags":["regex","grep","validation"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}