rust-lang/rust-analyzer · error
Invalid name `{}`: cannot rename to a keyword
Error message
Invalid name `{}`: cannot rename to a keyword What it means
`IdentifierKind::classify` (crates/ide-db/src/rename.rs:829) validates a proposed new name by lexing it as a single Rust token. If the name lexes to a keyword, only a small set is permitted: `self` (LowercaseSelf) and path keywords that become valid idents via raw-name representation (`_ => Ok(...Ident)`). The reserved path keywords `crate`, `super`, and `Self` can never be binding names, so the method bails with 'cannot rename to a keyword'.
Source
Thrown at crates/ide-db/src/rename.rs:829
Underscore,
LowercaseSelf,
}
impl IdentifierKind {
pub fn classify(edition: Edition, new_name: &str) -> Result<(Name, IdentifierKind)> {
match parser::LexedStr::single_token(edition, new_name) {
Some(res) => match res {
(SyntaxKind::IDENT, _) => Ok((Name::new_root(new_name), IdentifierKind::Ident)),
(T![_], _) => {
Ok((Name::new_symbol_root(sym::underscore), IdentifierKind::Underscore))
}
(SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
Ok((Name::new_lifetime(new_name), IdentifierKind::Lifetime))
}
_ if SyntaxKind::from_keyword(new_name, edition).is_some() => match new_name {
"self" => Ok((Name::new_root(new_name), IdentifierKind::LowercaseSelf)),
"crate" | "super" | "Self" => {
bail!("Invalid name `{}`: cannot rename to a keyword", new_name)
}
_ => Ok((Name::new_root(new_name), IdentifierKind::Ident)),
},
(_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
(_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
},
None => bail!("Invalid name `{}`: not an identifier", new_name),
}
}
}
View on GitHub (pinned to e8f7e90aa3)
Solutions
- Choose a legal identifier that is not one of `crate`, `super`, or `Self` (e.g. `self_param` instead of `self`-like keywords).
- If you wanted path-component semantics, rename the module/item to a normal name and update `use` paths instead.
- For a type alias intent, keep the original name and add `type SelfAlias = ...;` rather than renaming.
Example fix
// before: LSP rename request
{ "newName": "Self" }
// after
{ "newName": "SelfType" } Defensive patterns
Strategy: validation
Validate before calling
const RESERVED: [&str; 3] = ["crate", "super", "Self"];
fn validate_rename_name(new_name: &str) -> Result<(), String> {
if RESERVED.contains(&new_name) {
return Err(format!("cannot rename to keyword `{new_name}`"));
}
Ok(())
} Type guard
fn is_legal_rust_ident(s: &str) -> bool {
let mut cs = s.chars();
matches!(cs.next(), Some(c) if c.is_alphabetic() || c == '_')
&& cs.all(|c| c.is_alphanumeric() || c == '_')
&& !matches!(s, "crate" | "super" | "Self")
} Prevention
- Validate candidate names against the reserved list crate/super/Self before sending rename.
- Remember `self` and raw keywords (r#fn) are allowed but crate/super/Self never are.
- Use rustc's own keyword list when generating names programmatically.
- Show the error message text to users in editor UIs; it names the offending keyword.
When it happens
Trigger: Calling rename (textDocument/rename) with newName equal to `crate`, `super`, or `Self` on any item; the name passes the single-token check, matches `SyntaxKind::from_keyword`, and hits the explicit bail arm at rename.rs:829.
Common situations: User (or an LLM/refactoring script driving the LSP) types `Self` intending a struct-like alias, or `super`/`crate` intending a path segment rename — none of which are legal identifier positions in Rust.
Related errors
- Invalid name `{}`: {}
- Cannot rename local to self outside of function
- Method already has a self parameter
- Only the first parameter may be renamed to self
- No file available to rename
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/bad8b9538fe43440.
Report an issue: GitHub.