rust-lang/rust-analyzer · error
Invalid name `{}`: not an identifier
Error message
Invalid name `{}`: not an identifier What it means
For non-lifetime definitions, `rename_reference` requires the classified name to be `Ident` or `Underscore`. A lifetime-shaped name (starts with `'`, classified `IdentifierKind::Lifetime`) is invalid for ordinary identifiers, so the rename bails with "Invalid name `{}`: not an identifier". `cov_mark::hit!(rename_not_an_ident_ref)` marks this path in tests.
Source
Thrown at crates/ide-db/src/rename.rs:382
bail!(
"Invalid name `{}`: not a lifetime identifier",
new_name.display(sema.db, edition)
);
}
IdentifierKind::Ident => {
new_name = Name::new_lifetime(&format!("'{}", new_name.as_str()))
}
IdentifierKind::Lifetime => (),
IdentifierKind::LowercaseSelf => bail!(
"Invalid name `{}`: not a lifetime identifier",
new_name.display(sema.db, edition)
),
}
} else {
match ident_kind {
IdentifierKind::Lifetime => {
cov_mark::hit!(rename_not_an_ident_ref);
bail!("Invalid name `{}`: not an identifier", new_name.display(sema.db, edition));
}
IdentifierKind::Ident => cov_mark::hit!(rename_non_local),
IdentifierKind::Underscore => (),
IdentifierKind::LowercaseSelf => {
bail!(
"Invalid name `{}`: cannot rename to `self`",
new_name.display(sema.db, edition)
);
}
}
}
let def = convert_to_def_in_trait(sema.db, def);
let usages = def.usages(sema).all();
if !usages.is_empty() && ident_kind == IdentifierKind::Underscore {
cov_mark::hit!(rename_underscore_multiple);
bail!("Cannot rename reference to `_` as it is being referenced multiple times");View on GitHub (pinned to e8f7e90aa3)
Solutions
- Remove the leading apostrophe and pass a plain identifier (e.g. `y` instead of `'y`).
- If renaming a lifetime was intended, place the cursor on the lifetime parameter first.
- Client-side, strip or reject names beginning with `'` when the target is not a lifetime.
Example fix
// before rename(local_def, "'a")?; // Err: not an identifier // after rename(local_def, "a")?; // ok
Defensive patterns
Strategy: validation
Validate before calling
if !is_lifetime_target(def) && new_name.starts_with('\'') {
return Err(anyhow!("identifiers must not start with an apostrophe"));
} Type guard
fn is_plain_identifier(s: &str) -> bool {
let mut cs = s.chars();
matches!(cs.next(), Some(c) if c.is_ascii_alphabetic() || c == '_') && cs.all(|c| c.is_ascii_alphanumeric() || c == '_')
} Try / catch
match def.rename(sema, new_name, ...) {
Err(e) if e.to_string().contains("not an identifier") => eprintln!("drop the leading apostrophe for non-lifetime names"),
other => other?,
} Prevention
- Strip stray leading `'` from rename input unless the target is a lifetime.
- Match the IdentifierKind classification to the definition kind before renaming.
- Keep per-target-kind input validation in the client.
When it happens
Trigger: Renaming any non-lifetime `Definition` (e.g. a local variable, function, or module) with a lifetime-shaped new name such as `"'a"` at crates/ide-db/src/rename.rs:382.
Common situations: User selects a variable like `x` and types `'a` into the rename box (often by accidentally leaving an apostrophe from a previous lifetime rename), and the IDE rejects it.
Related errors
- Invalid name `{0}`: cannot rename module to {0}
- 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/91b47c497c81135d.
Report an issue: GitHub.