rust-lang/cargo · error
subcommand is required, add a subcommand to the command alia
Error message
subcommand is required, add a subcommand to the command alias `alias.{cmd}` What it means
From expand_aliases (src/bin/cargo/cli.rs:376-381). After resolving a user alias from config, Cargo re-parses the alias's argument list with no_binary_name and reads new_args.subcommand_name(). If there is no subcommand (the alias consists only of flags, is empty, or names something that isn't a builtin/external command), it errors asking you to add a subcommand to alias.{cmd}.
Source
Thrown at src/bin/cargo/cli.rs:377
let mut alias = alias
.into_iter()
.map(|s| OsString::from(s))
.collect::<Vec<_>>();
alias.extend(
sub_args
.get_many::<OsString>("")
.unwrap_or_default()
.cloned(),
);
// new_args strips out everything before the subcommand, so
// capture those global options now.
// Note that an alias to an external command will not receive
// these arguments. That may be confusing, but such is life.
let global_args = GlobalArgs::new(sub_args);
let new_args = cli(gctx).no_binary_name(true).try_get_matches_from(alias)?;
let Some(new_cmd) = new_args.subcommand_name() else {
return Err(anyhow!(
"subcommand is required, add a subcommand to the command alias `alias.{cmd}`"
)
.into());
};
already_expanded.push(cmd.to_string());
if already_expanded.contains(&new_cmd.to_string()) {
// Crash if the aliases are corecursive / unresolvable
return Err(anyhow!(
"alias {} has unresolvable recursive definition: {} -> {}",
already_expanded[0],
already_expanded.join(" -> "),
new_cmd,
)
.into());
}
let (expanded_args, _) = expand_aliases(gctx, new_args, already_expanded)?;View on GitHub (pinned to 0e07a15537)
Solutions
- Edit .cargo/config.toml so the alias starts with a valid cargo subcommand, e.g. `foo = "build --release"`.
- If the alias targets an external command, install `cargo-<name>` (it must be on PATH).
- Check for typos: the first token must exactly match a known subcommand.
- Run `cargo help` to list valid builtins the alias can invoke.
Example fix
# before (.cargo/config.toml) [alias] foo = ["--verbose"] # after [alias] foo = "build --verbose"
Defensive patterns
Strategy: validation
Validate before calling
// Validate an alias definition starts with a known subcommand token
fn alias_has_subcommand(def: &[String], known: &std::collections::HashSet<String>) -> bool {
def.iter().next()
.map(|t| known.contains(t))
.unwrap_or(false)
} Type guard
fn is_well_formed_alias(def: &str) -> bool {
let first = def.split_whitespace().next();
first.is_some() && !first.unwrap().starts_with('-')
} Prevention
- Always begin an alias definition with a concrete subcommand name.
- Lint .cargo/config.toml aliases in CI (parse and check the first token).
- Install external cargo-<ext> commands before aliasing to them.
When it happens
Trigger: A .cargo/config.toml entry like [alias] foo = "" or alias.foo = ["--verbose"]. An alias whose first token is neither a builtin subcommand, a builtin alias, nor an installed cargo-<ext> external. Programmatically building an alias config without a leading command token.
Common situations: Typo in the alias definition; alias referencing a command that isn't installed yet; refactoring config and leaving a dangling alias; an alias meant to forward args but missing the target command.
Related errors
- alias {} has unresolvable recursive definition: {} -> {}
- subcommand is required, but `{alias_name}` is empty
- argument for --color must be auto, always, or never, but fou
- invalid character `+` in dependency name: `+{toolchain}`
- feature `{feature}` must be qualified by the dependency it's
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/80f6bffebab19ace.json.
Report an issue: GitHub.