rust-lang/rust-analyzer · error
Invalid name `{0}`: cannot rename module to {0}
Error message
Invalid name `{0}`: cannot rename module to {0} What it means
`rename_mod` classifies the proposed new name via `IdentifierKind::classify` and only accepts a plain identifier for modules. If the new name is not an `Ident` (e.g. a lifetime, `_`, or `self`), it fails with "Invalid name ... cannot rename module to {0}" because module names must be valid non-underscore identifiers.
Source
Thrown at crates/ide-db/src/rename.rs:270
}
}
fn rename_mod(
sema: &Semantics<'_, RootDatabase>,
module: hir::Module,
new_name: &str,
) -> Result<SourceChange> {
let mut source_change = SourceChange::default();
if module.is_crate_root(sema.db) {
return Ok(source_change);
}
let InFile { file_id, value: def_source } = module.definition_source(sema.db);
let edition = file_id.edition(sema.db);
let (new_name, kind) = IdentifierKind::classify(edition, new_name)?;
if kind != IdentifierKind::Ident {
bail!(
"Invalid name `{0}`: cannot rename module to {0}",
new_name.display(sema.db, edition)
);
}
if let ModuleSource::SourceFile(..) = def_source {
let anchor = file_id.original_file(sema.db).file_id(sema.db);
let is_mod_rs = module.is_mod_rs(sema.db);
let has_detached_child = module.children(sema.db).any(|child| !child.is_inline(sema.db));
// Module exists in a named file
if !is_mod_rs {
let path = format!("{}.rs", new_name.as_str());
let dst = AnchoredPathBuf { anchor, path };
source_change.push_file_system_edit(FileSystemEdit::MoveFile { src: anchor, dst })
}
// Rename the dir if:View on GitHub (pinned to e8f7e90aa3)
Solutions
- Provide a valid Rust identifier as the new module name (letters/digits/underscores, not starting with a digit, not `_` or `self`).
- If the desired name contains dashes or spaces (e.g. from a directory name), convert it to snake_case first.
- Pre-validate the name in the client with an identifier check before issuing the rename request.
Example fix
// before rename(mod_def, "my-mod")?; // invalid: not an Ident // after rename(mod_def, "my_mod")?; // valid snake_case identifier
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_mod_name(name: &str) -> bool {
!name.is_empty()
&& name != "_"
&& name != "self"
&& !name.starts_with('\'')
&& name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
&& !name.chars().next().unwrap().is_ascii_digit()
} Type guard
fn is_plain_ident(s: &str) -> bool {
syn::parse_str::<syn::Ident>(s).is_ok() && s != "self" && s != "_"
} Try / catch
match def.rename(sema, new_name, ...) {
Err(e) if e.to_string().contains("cannot rename module to") => eprintln!("module names must be plain identifiers"),
other => other?,
} Prevention
- Sanitize rename input to snake_case identifiers before sending module renames.
- Reject `_`, `self`, and lifetime-shaped inputs in the rename prompt.
- Convert dashed directory names to underscores when deriving module names.
When it happens
Trigger: Renaming a `Definition::Module` whose new name classifies as `Lifetime`, `Underscore`, or `LowercaseSelf` — e.g. `rename(mod_def, "'a")`, `rename(mod_def, "_")`, or `rename(mod_def, "self")`.
Common situations: User selects a module declaration and types `self`, `_`, or a quoted/lifetime-like string in the rename input box; the IDE rejects it.
Related errors
- Invalid name `{}`: not an identifier
- Cannot rename builtin type
- Cannot rename a builtin attr.
- Cannot rename `Self`
- Invalid name `{}`: not a lifetime identifier
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/a692068b532b61e2.
Report an issue: GitHub.