helix-editor/helix · warning

Failed to compile regex

Error message

Failed to compile regex

What it means

:global-search builds its matcher with RegexMatcherBuilder (the regex crate, smart-case and multi-line enabled). Queries that are not valid regex — unbalanced parens/brackets, dangling or reversed quantifiers ('*x', 'a{2,1}'), or constructs regex does not support like look-around and backreferences — fail to compile; the picker shows 'Failed to compile regex' and logs the underlying error at info level. On the next keystroke a successful compile clears the statusline error.

Source

Thrown at helix-term/src/commands.rs:2637

        let documents: Vec<_> = editor
            .documents()
            .map(|doc| (doc.path().map(ToOwned::to_owned), doc.text().to_owned()))
            .collect();

        let matcher = match RegexMatcherBuilder::new()
            .case_smart(config.smart_case)
            .multi_line(true)
            .build(query)
        {
            Ok(matcher) => {
                // Clear any "Failed to compile regex" errors out of the statusline.
                editor.clear_status();
                matcher
            }
            Err(err) => {
                log::info!("Failed to compile search pattern in global search: {}", err);
                return async { Err(anyhow::anyhow!("Failed to compile regex")) }.boxed();
            }
        };

        let dedup_symlinks = config.file_picker_config.deduplicate_links;
        let absolute_root = search_root
            .canonicalize()
            .unwrap_or_else(|_| search_root.clone());

        let injector = injector.clone();
        async move {
            let searcher = SearcherBuilder::new()
                .binary_detection(BinaryDetection::quit(b'\x00'))
                .multi_line(true)
                .build();
            WalkBuilder::new(search_root)
                .hidden(config.file_picker_config.hidden)
                .parents(config.file_picker_config.parents)
                .ignore(config.file_picker_config.ignore)

View on GitHub (pinned to 079a789e8c)

Solutions

  1. Escape metacharacters with backslashes: 'foo\(bar\)' instead of 'foo(bar)'.
  2. Drop unsupported constructs (look-around, backreferences) — the regex crate cannot compile them; reformulate with classes/alternation.
  3. For pure literal search, escape every one of . * + ? ( ) [ ] { } | ^ $ \ or start from a metacharacter-free substring.

Example fix

# before: unbalanced group
foo(bar
# after
foo\(bar\)
Defensive patterns

Strategy: validation

Validate before calling

// gate the search on the same syntax the matcher uses
if regex::Regex::new(query).is_ok() {
    // safe to feed :global-search's dynamic query
}

Type guard

fn is_valid_search_regex(q: &str) -> bool {
    regex::Regex::new(q).is_ok()
}

Prevention

When it happens

Trigger: Typing '(' alone, '(?=foo)', '*bar', 'a{2,1}', or a literal string containing metacharacters like 'f(x)+' or 'C++(' into the global-search prompt while it dynamically re-runs.

Common situations: Searching literal text full of regex metacharacters (code snippets, 'foo(bar)', 'a.b*c'); PCRE habits (look-ahead/behind, backreferences) ported from grep -P or other editors; partially typed patterns in the dynamic query.

Related errors


AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16). Data as JSON: /api/errors/6e2582b343282937. Report an issue: GitHub.