{"record":{"id":"02a7c5c05199aac4","repo":"derailed/k9s","slug":"invalid-rx-filter-q-w","errorCode":null,"errorMessage":"invalid rx filter %q: %w","messagePattern":"invalid rx filter %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/model1/table_data.go","lineNumber":176,"sourceCode":"\t\ttd.rowEvents = rr\n\t} else {\n\t\tslog.Error(\"RX filter failed\", slogs.Error, err)\n\t}\n\n\treturn td\n}\n\nfunc (t *TableData) rxFilter(q string, inverse bool) (*RowEvents, error) {\n\tif strings.Contains(q, \" \") {\n\t\treturn t.rowEvents, nil\n\t}\n\n\tif inverse {\n\t\tq = q[1:]\n\t}\n\trx, err := regexp.Compile(`(?i)(` + q + `)`)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid rx filter %q: %w\", q, err)\n\t}\n\n\tvidx := t.header.FilterColIndices(t.namespace, true)\n\trr := NewRowEvents(t.RowCount() / 2)\n\tt.rowEvents.Range(func(_ int, re RowEvent) bool {\n\t\tff := make([]string, 0, len(re.Row.Fields))\n\t\tfor idx, r := range re.Row.Fields {\n\t\t\tif !vidx.Has(idx) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tff = append(ff, r)\n\t\t}\n\t\tmatch := rx.MatchString(strings.Join(ff, spacer))\n\t\tif (inverse && !match) || (!inverse && match) {\n\t\t\trr.Add(re)\n\t\t}\n\n\t\treturn true","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/model1/table_data.go#L158-L194","documentation":"TableData.rxFilter compiles the user's filter string as a case-insensitive regex ((?i)(q)) after stripping a leading '!' for inverse mode; multi-word queries are treated as plain text and skip regex. Any string that is not a valid Go regex (unbalanced parentheses, stray '*', trailing backslash, bad character class) fails regexp.Compile and is reported with the compile error wrapped.","triggerScenarios":"Typing a filter in a k9s list view containing regex metacharacters, e.g. 'my-app(', '500*', 'pod\\', '[a-' — any invalid Go RE2 syntax. Queries with spaces never hit this (plain match); a leading '!' is removed before compiling so '!(' fails on the '(' alone.","commonSituations":"Copy-pasting strings with glob-style wildcards ('*.prod') or shell globs into the filter bar; assuming PCRE syntax (lookaheads like (?=...) are unsupported in RE2); trailing backslashes from partial typing.","solutions":["Fix the regex: balance groups, escape metacharacters (\\. \\* \\[ \\( ) as literals","RE2 has no lookaround/backreferences — replace (?=x) patterns with simpler alternations","Add a space to force plain-text matching instead of regex (multi-word queries bypass regex)","Test the pattern first: echo 'name' | grep -E '(?i)(your-pattern)' or use Go's regexp to validate"],"exampleFix":"# before: glob-style filter (invalid regex)\n*.prod\\\n\n# after: escaped, valid regex\n.*\\.prod","handlingStrategy":"validation","validationCode":"// Pre-validate the filter the same way the view does.\nquery := strings.TrimPrefix(q, \"!\") // inverse prefix is stripped first\nif _, err := regexp.Compile(\"(?i)(\" + query + \")\"); err != nil {\n    return fmt.Errorf(\"bad filter %q: %w — escape regex metacharacters or add a space for plain text\", q, err)\n}","typeGuard":null,"tryCatchPattern":"events, err := td.rxFilter(q, inverse)\nif err != nil && strings.Contains(err.Error(), \"invalid rx filter\") {\n    // keep the session alive: revert to unfiltered view and show a hint\n    ui.Flash().Errf(\"Invalid regex filter %q — see :help filter\", q)\n    return td.rowEvents, nil\n}","preventionTips":["Remember RE2/Go regex: no lookaheads, no backreferences — use simpler patterns","Escape literals (\\. \\* \\+ \\( \\) \\[ ) when filtering by names containing dots or wildcards","Include a space in the query to force plain-text (non-regex) matching"],"tags":["regex","filter","ui","re2","k9s"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}