rust-lang/rust-analyzer · error
Failed to make expr node `{node}` from text `{text}`
Error message
Failed to make expr node `{node}` from text `{text}` What it means
`expr_from_text(_with_edition)` in `syntax::ast::make` parses the snippet as a Rust expression and casts the first descendant matching type `E`. If the parse yields no node of the expected expression type, it panics naming the type and the offending text. This is an internal invariant failure: an `make::expr_*` constructor was given text that does not produce the expected expression node.
Source
Thrown at crates/syntax/src/ast/make.rs:1386
}
pub fn expr_let(pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr {
expr_from_text(&format!("while let {pattern} = {expr} {{}}"))
}
#[track_caller]
fn expr_from_text<E: Into<ast::Expr> + AstNode>(text: &str) -> E {
expr_from_text_with_edition(text, Edition::CURRENT)
}
#[track_caller]
fn expr_from_text_with_edition<E: Into<ast::Expr> + AstNode>(text: &str, edition: Edition) -> E {
let parse = ast::Expr::parse(text, edition);
let node = match parse.tree().syntax().descendants().find_map(E::cast) {
Some(it) => it,
None => {
let node = std::any::type_name::<E>();
panic!("Failed to make expr node `{node}` from text `{text}`")
}
};
let node = node.clone_subtree();
assert_eq!(node.syntax().text_range().start(), 0.into());
node
}
#[track_caller]
fn ast_from_text<N: AstNode>(text: &str) -> N {
ast_from_text_with_edition(text, Edition::CURRENT)
}
#[track_caller]
fn ast_from_text_with_edition<N: AstNode>(text: &str, edition: Edition) -> N {
let parse = SourceFile::parse(text, edition);
let node = match parse.tree().syntax().descendants().find_map(N::cast) {
Some(it) => it,
None => {View on GitHub (pinned to e8f7e90aa3)
Solutions
- Check `{text}` in the panic message and ensure it is a single well-formed Rust expression of the type named by `{node}`.
- Verify the fragment by running `ast::Expr::parse(text, edition)` and inspecting `parse.errors()` before constructing nodes.
- If text comes from user code, sanitize/validate it (extract via parsing and re-serialize) instead of passing raw text.
- Confirm the correct `Edition`; use the `_with_edition` variant explicitly for edition-sensitive syntax.
Example fix
// before (panics: `let x = 1;` is not an expr)
let e = make::expr_call(f, ta(make::expr_from_text("let x = 1;")));
// after
let e = make::expr_call(f, ta(make::expr_from_text("1 + 2"))); Defensive patterns
Strategy: validation
Validate before calling
fn expr_text_is_valid(text: &str, edition: span::Edition) -> bool {
let parse = syntax::ast::Expr::parse(text, edition);
parse.errors().is_empty()
&& parse.syntax().first_child_or_token().is_some()
} Type guard
fn as_expr_node<N: Into<syntax::ast::Expr> + syntax::AstNode>(
text: &str,
edition: span::Edition,
) -> Option<N> {
let parse = syntax::ast::Expr::parse(text, edition);
parse.tree().syntax().descendants().find_map(N::cast)
} Prevention
- Validate that snippet text parses as an expression before passing it to `make::expr_*` constructors.
- Never feed raw user code or interpolated strings into make constructors without sanitizing.
- Check `parse.errors()` during development for generated fragments.
- Use the correct `Edition` via the `_with_edition` variants.
When it happens
Trigger: Calling a `make::expr_*` constructor with text that parses to a different syntactic category than `E` or fails to parse entirely (empty string, a statement like `let x = 1;`, a type, or edition-invalid syntax), so `E::cast` finds nothing.
Common situations: Interpolating untrusted or user-edited source text into `format!` templates fed to make constructors; assist/fix logic generating empty or malformed fragments; edition mismatches where the expression is only valid in one edition.
Related errors
- Failed to make ast node `{node}` from text `{text}`
- Can't find SyntaxNodePtr {:?} in AstIdMap: {:?}
- AstIdMap node mismatch with node `{ptr:?}`
- Can't find ast id {:?} in AstIdMap: {:?}
- dynamic `SyntaxKind` for `AstNode::kind()`
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/942c922c148b393b.
Report an issue: GitHub.