rust-lang/rust-analyzer · error

Failed to parse pattern: {}

Error message

Failed to parse pattern: {}

What it means

This error comes from the structural search/replace (SSR) pattern tokenizer. Before splitting the pattern into tokens, the pattern source is run through the rust-analyzer lexer; if the lexer reports any error (unbalanced quotes, bad characters, unterminated constructs), the whole pattern is rejected with this message carrying the underlying lexer error text. It fires early in parse_pattern via tokenize, so nothing is matched at all.

Source

Thrown at crates/ide-ssr/src/parsing.rs:260

        if let PatternElement::Placeholder(placeholder) = p {
            if !defined_placeholders.contains(&placeholder.ident) {
                undefined.push(placeholder.ident.to_string());
            }
            if !placeholder.constraints.is_empty() {
                bail!("Replacement placeholders cannot have constraints");
            }
        }
    }
    if !undefined.is_empty() {
        bail!("Replacement contains undefined placeholders: {}", undefined.join(", "));
    }
    Ok(())
}

fn tokenize(source: &str) -> Result<Vec<Token>, SsrError> {
    let lexed = parser::LexedStr::new(parser::Edition::CURRENT, source);
    if let Some((_, first_error)) = lexed.errors().next() {
        bail!("Failed to parse pattern: {}", first_error);
    }
    let mut tokens: Vec<Token> = Vec::new();
    for i in 0..lexed.len() {
        tokens.push(Token { kind: lexed.kind(i), text: lexed.text(i).into() });
    }
    Ok(tokens)
}

fn parse_placeholder(tokens: &mut std::vec::IntoIter<Token>) -> Result<Placeholder, SsrError> {
    let mut name = None;
    let mut constraints = Vec::new();
    if let Some(token) = tokens.next() {
        match token.kind {
            SyntaxKind::IDENT => {
                name = Some(token.text);
            }
            T!['{'] => {
                let token =

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Read the embedded first_error text and fix the lexical problem (unterminated string/comment, illegal character) in the pattern
  2. Verify the pattern is a complete, lexable Rust fragment before passing it to the SSR API
  3. Escape special characters (quotes, braces) that were introduced by shell/string interpolation

Example fix

// before
let pattern = "fn foo( -> u32"; // unterminated paren/lexer garbage
// after
let pattern = "fn foo() -> u32";
Defensive patterns

Strategy: validation

Validate before calling

fn is_lexable(pattern: &str) -> bool {
    let lexed = ide_ssr::parsing_lexer(pattern);
    lexed.errors().next().is_none()
}
// reject patterns where is_lexable returns false before calling the SSR API

Type guard

fn is_valid_ssr_pattern(p: &str) -> bool {
    !p.trim().is_empty() && p.chars().all(|c| !matches!(c, '\u{0}'))
}

Try / catch

match SearchPattern::new(&pattern) {
    Ok(p) => apply(p),
    Err(e) if e.message.starts_with("Failed to parse pattern") => {
        eprintln!("Invalid SSR pattern (lexer): {}", e.message);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling any ide-ssr API that parses a search or replace pattern (e.g. parse_pattern via SearchPattern::new) with source containing a lexing error, such as an unterminated string literal or invalid character, as detected by parser::LexedStr::new errors().

Common situations: Typing an SSR search pattern in the IDE's structural search box with a stray or unbalanced quote; programmatically building patterns with string interpolation that leaves broken syntax; copying a code snippet that includes an incomplete fragment.

Understand the failure class

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/3a573ceff5050aaa. Report an issue: GitHub.