rust-lang/cargo · error · anyhow::Error
invalid package name `{}`: it is a Rust keyword{}
Error message
invalid package name `{}`: it is a Rust keyword{} What it means
check_name rejects a package name that exactly matches a Rust keyword (detected via restricted_names::is_keyword). Keywords like `fn`, `match`, `crate`, `impl`, `type`, `pub` cannot be used as a crate name because they would collide with the language grammar when the crate is referenced as an identifier. The trailing {help} offers a [[bin]] override path when applicable.
Source
Thrown at src/ops/cargo_new.rs:210
This can be done by setting the binary filename to `src/bin/{name}.rs` \
or change the name in Cargo.toml with:\n\
\n \
[[bin]]\n \
name = \"{name}\"\n \
path = \"src/main.rs\"\n\
",
name = name
));
}
help
};
PackageName::new(name).map_err(|err| {
let help = bin_help();
anyhow::anyhow!("{err}{help}")
})?;
if restricted_names::is_keyword(name) {
anyhow::bail!(
"invalid package name `{}`: it is a Rust keyword{}",
name,
bin_help()
);
}
if restricted_names::is_conflicting_artifact_name(name) {
if has_bin {
anyhow::bail!(
"invalid package name `{}`: \
it conflicts with cargo's build directory names{}",
name,
name_help
);
} else {
shell.warn(format!(
"package `{}` will not support binary \
executables with that name, \
it conflicts with cargo's build directory names",View on GitHub (pinned to 0e07a15537)
Solutions
- Pick a non-keyword name, e.g. `match` -> `matcher` or `match-utils`
- Use `--name <non-keyword>` to override the directory-derived name
- Rename the containing directory before running cargo new
Example fix
# before cargo new match # after cargo new matcher # or: cargo new match --name matcher
Defensive patterns
Strategy: validation
Validate before calling
const KEYWORDS: &[&str] = &[
"as","break","const","continue","crate","dyn","else","enum","extern","false","fn","for",
"if","impl","in","let","loop","match","mod","move","mut","pub","ref","return","self","Self",
"static","struct","super","trait","true","type","unsafe","use","where","while","async","await",
];
fn is_rust_keyword(name: &str) -> bool { KEYWORDS.contains(&name) } Type guard
const KEYWORDS = new Set(['fn','match','crate','impl','type','pub','let','if','else','for','while','loop','return','struct','enum','trait','mod','use','move','self','Self','super','static','const','unsafe','as','in','ref','dyn','where','true','false','extern','break','continue','mut','async','await']);
function isNotKeyword(name: string): boolean { return !KEYWORDS.has(name); } Prevention
- Cross-check candidate names against the rust-lang keyword list before cargo new
- Use a name-linter in project generators
- Avoid naming crates after the language feature they exercise
When it happens
Trigger: `cargo new match`, `cargo new --name crate`, or running `cargo new` inside a directory literally named `fn`, `impl`, `self`, `super`, etc. is_keyword(name) at cargo_new.rs:209 returns true.
Common situations: Creating a crate for a tutorial about a language feature and naively naming it after the keyword; directory created by a framework generator that used a keyword; copy of an example whose name happens to be reserved.
Related errors
- {err}{help}
- invalid package name `{}`: it conflicts with cargo's build d
- invalid package name `test`: it conflicts with Rust's built-
- invalid package name `{}`: it is a reserved Windows filename
- unknown vcs specification: `{}`
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/8ed455a1939b8af1.json.
Report an issue: GitHub.