{"record":{"id":"162c16b004aa0b6c","repo":"rust-lang/rust-analyzer","slug":"expected-found-end-of-stream","errorCode":null,"errorMessage":"Expected {} found end of stream","messagePattern":"Expected (.+?) found end of stream","errorType":"validation","errorClass":"SsrError","httpStatus":null,"severity":"error","filePath":"crates/ide-ssr/src/parsing.rs","lineNumber":340,"sourceCode":"        }\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,\n            ident: Var(name.to_string()),\n        }","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide-ssr/src/parsing.rs#L322-L358","documentation":"Same expect_token check as 'Expected {} found {}', but this variant fires when the token stream is exhausted: the expected token (e.g. the closing ')' of a constraint) was never present. The pattern simply ends prematurely inside a constraint.","triggerScenarios":"Truncated pattern input such as '$x:kind(literal' or '$x:not(' reaching parse_constraint's expect_token call with an empty iterator.","commonSituations":"Cutting off an SSR pattern mid-edit in the search box; programmatically building patterns and truncating strings; missing closing brace/paren combinations that consume the rest of the input.","solutions":["Close all open constraint parentheses: kind(...), not(...)","Complete the truncated pattern and re-run the parse","If building patterns programmatically, validate balanced parens before calling the API"],"exampleFix":"// before\nlet pattern = \"$x:kind(literal\";\n// after\nlet pattern = \"$x:kind(literal)\";","handlingStrategy":"validation","validationCode":"fn complete_constraints(p: &str) -> bool {\n    let mut depth = 0i32;\n    for c in p.chars() {\n        match c {\n            '(' => depth += 1,\n            ')' => depth -= 1,\n            _ => {}\n        }\n    }\n    // pattern must not end inside an open constraint\n    depth == 0 && !p.trim_end().ends_with('(')\n}\n","typeGuard":null,"tryCatchPattern":"match parse_pattern(pattern) {\n    Ok(p) => use_pattern(p),\n    Err(e) if e.message.contains(\"end of stream\") => {\n        eprintln!(\"Pattern ended mid-constraint; close all parentheses\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Ensure the full pattern string is passed (no truncation)","Close every '(' with a ')' before submitting","Check brace and paren balance together for ${...} placeholders","Validate patterns programmatically before calling the SSR API"],"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"}