{"record":{"id":"4267c179664e50ad","repo":"rust-lang/rust-analyzer","slug":"expected-found","errorCode":null,"errorMessage":"Expected {} found {}","messagePattern":"Expected (.+?) found (.+?)","errorType":"validation","errorClass":"SsrError","httpStatus":null,"severity":"error","filePath":"crates/ide-ssr/src/parsing.rs","lineNumber":338,"sourceCode":"            expect_token(tokens, \")\")?;\n            Ok(Constraint::Kind(NodeKind::from(&t.text)?))\n        }\n        \"not\" => {\n            expect_token(tokens, \"(\")?;\n            let sub = parse_constraint(tokens)?;\n            expect_token(tokens, \")\")?;\n            Ok(Constraint::Not(Box::new(sub)))\n        }\n        x => bail!(\"Unsupported constraint type '{}'\", x),\n    }\n}\n\nfn expect_token(tokens: &mut std::vec::IntoIter<Token>, expected: &str) -> Result<(), SsrError> {\n    if let Some(t) = tokens.next() {\n        if t.text == expected {\n            return Ok(());\n        }\n        bail!(\"Expected {} found {}\", expected, t.text);\n    }\n    bail!(\"Expected {} found end of stream\", expected);\n}\n\nimpl NodeKind {\n    fn from(name: &SmolStr) -> Result<NodeKind, SsrError> {\n        Ok(match name.as_str() {\n            \"literal\" => NodeKind::Literal,\n            _ => bail!(\"Unknown node kind '{}'\", name),\n        })\n    }\n}\n\nimpl Placeholder {\n    fn new(name: SmolStr, constraints: Vec<Constraint>) -> Self {\n        Self {\n            stand_in_name: format!(\"__placeholder_{name}\"),\n            constraints,","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide-ssr/src/parsing.rs#L320-L356","documentation":"expect_token consumes the next token from the pattern's token stream and requires its text to equal the expected string (e.g. '(' or ')'). If a token exists but its text differs, this error reports both the expected and found text. It is used by parse_constraint to validate the parentheses around kind(...) and not(...) constraints.","triggerScenarios":"kind constraint missing its '(' or ')' but with some other token present instead, e.g. kind literal) or kind(literal, producing 'Expected ( found literal' style messages.","commonSituations":"Omitting parentheses around kind(...) arguments; stray commas or spaces-as-tokens inside constraint syntax; copy/paste mangling of constraint examples.","solutions":["Ensure every constraint argument is fully parenthesized: kind(literal), not(kind(literal))","Compare the 'found' text in the message against your pattern to locate the mismatched character","Balance parentheses when nesting not constraints"],"exampleFix":"// before\nlet pattern = \"$x:kind literal\";\n// after\nlet pattern = \"$x:kind(literal)\";","handlingStrategy":"validation","validationCode":"fn constraint_parens_balanced(p: &str) -> bool {\n    let mut depth = 0i32;\n    for c in p.chars() {\n        match c {\n            '(' => depth += 1,\n            ')' => {\n                depth -= 1;\n                if depth < 0 { return false; }\n            }\n            _ => {}\n        }\n    }\n    depth == 0\n}\n","typeGuard":null,"tryCatchPattern":"match parse_pattern(pattern) {\n    Ok(p) => use_pattern(p),\n    Err(e) if e.message.starts_with(\"Expected \") => {\n        eprintln!(\"Constraint parentheses mismatch: {}\", e.message);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always write constraints as name(argument)","Count parens when nesting not(kind(...))","Remove stray tokens between constraint names and their arguments","Validate patterns with a quick parse before applying them"],"tags":["rust","parsing","ssr","constraints"],"backgroundTag":"ssr-pattern-parse-error","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}