rust-lang/rust-analyzer · error
Failed to make ast node `{node}` from text `{text}`
Error message
Failed to make ast node `{node}` from text `{text}` What it means
`ast_from_text(_with_edition)` in `syntax::ast::make` parses a snippet as a `SourceFile` and casts the first descendant to the requested AST node type `N`. If the tree contains no node of type `N` (malformed text or a different syntactic category), it panics with the type name and text. Nearly all `make::*` constructors route through this helper, so this panic means a constructor was handed text it cannot build its node from.
Source
Thrown at crates/syntax/src/ast/make.rs:1406
};
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 => {
let node = std::any::type_name::<N>();
panic!("Failed to make ast node `{node}` from text `{text}`")
}
};
let node = node.clone_subtree();
assert_eq!(node.syntax().text_range().start(), 0.into());
node
}
pub fn token(kind: SyntaxKind) -> SyntaxToken {
tokens::SOURCE_FILE
.tree()
.syntax()
.descendants_with_tokens()
.filter_map(|it| it.into_token())
.find(|it| it.kind() == kind)
.unwrap_or_else(|| panic!("unhandled token: {kind:?}"))
}
pub mod tokens {View on GitHub (pinned to e8f7e90aa3)
Solutions
- Read `{node}` and `{text}` in the panic to identify which constructor template produced unparseable output.
- Fix the caller so interpolated fragments are syntactically valid (validate identifiers/paths before formatting).
- Reproduce the text and run `SourceFile::parse(text, edition)` to see parse errors, then adjust the template.
- If the syntax is edition-dependent, call the `_with_edition` constructor with the correct `Edition`.
- Add a unit test for the `make::` constructor with the previously failing input.
Example fix
// before (panics: `1 +` is not a valid path)
let p = make::path_from_text("1 +");
// after
let p = make::path_from_text("std::mem::drop"); Defensive patterns
Strategy: validation
Validate before calling
fn ast_text_is_valid(text: &str, edition: span::Edition) -> bool {
let parse = syntax::SourceFile::parse(text, edition);
parse.errors().is_empty()
} Type guard
fn as_ast_node<N: syntax::AstNode>(text: &str, edition: span::Edition) -> Option<N> {
let parse = syntax::SourceFile::parse(text, edition);
parse.tree().syntax().descendants().find_map(N::cast)
} Prevention
- Pre-parse template output with `SourceFile::parse` and assert no errors in tests.
- Validate interpolated identifiers/paths/types before formatting into make templates.
- Keep a unit test per `make::` constructor covering the exact template output.
- Pass the correct `Edition` when snippets use edition-specific syntax.
When it happens
Trigger: Any `make::*` constructor whose `format!` template was filled with malformed content — a bad name/signature in `make::fn_`, an invalid path in `make::path_from_text`, unbalanced delimiters, or an empty string — so `SourceFile::parse` yields no descendant castable to `N`.
Common situations: Buggy assists/syntax rewrites interpolating user identifiers containing spaces or operators into templates; empty-string arguments; edition-sensitive syntax fed with the wrong `Edition`; regressions after editing a `make::` template format string.
Related errors
- Failed to make expr 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/374d147d6d2e8c6a.
Report an issue: GitHub.