rtk-ai/rtk · error
dotnet: no subcommand specified
Error message
dotnet: no subcommand specified
What it means
RTK's dotnet passthrough handler requires at least one subcommand. run_passthrough bails before spawning `dotnet` when the args slice is empty, because a bare `rtk dotnet` has nothing to proxy or filter. The real `dotnet` CLI would print its help banner here, but RTK refuses rather than delegate an empty invocation.
Source
Thrown at src/cmds/dotnet/dotnet_cmd.rs:79
timer.track(
&format!("dotnet format {}", args.join(" ")),
&format!("rtk dotnet format {}", args.join(" ")),
&raw,
shown,
);
if cleanup_report_path {
if let Some(path) = report_path.as_deref() {
cleanup_temp_file(path);
}
}
Ok(result.exit_code)
}
pub fn run_passthrough(args: &[OsString], verbose: u8) -> Result<i32> {
if args.is_empty() {
anyhow::bail!("dotnet: no subcommand specified");
}
let timer = tracking::TimedExecution::start();
let subcommand = args[0].to_string_lossy().to_string();
let mut cmd = resolved_command("dotnet");
cmd.env(DOTNET_CLI_UI_LANGUAGE, DOTNET_CLI_UI_LANGUAGE_VALUE);
cmd.arg(&subcommand);
for arg in &args[1..] {
cmd.arg(arg);
}
if verbose > 0 {
eprintln!("Running: dotnet {} ...", subcommand);
}
let result =
exec_capture(&mut cmd).with_context(|| format!("Failed to run dotnet {}", subcommand))?;View on GitHub (pinned to d977e1c316)
Solutions
- Run rtk with an explicit dotnet subcommand: `rtk dotnet build`, `rtk dotnet test`, `rtk dotnet run`
- If you only wanted dotnet's own help/banner, delegate unfiltered: `rtk proxy dotnet` or plain `dotnet --help`
- Guard wrapper scripts before forwarding: `[ $# -gt 0 ] || { echo 'usage: rtk dotnet <subcommand>' >&2; exit 2; }`
Example fix
# before
rtk dotnet # args.is_empty() -> bail!("dotnet: no subcommand specified")
# after
rtk dotnet build --no-restore
# or let the bare CLI through unfiltered (still tracked in rtk gain)
rtk proxy dotnet Defensive patterns
Strategy: validation
Validate before calling
bash: # before invoking rtk, make sure a subcommand exists if [ $# -eq 0 ]; then echo "usage: rtk dotnet <subcommand> [args...]" >&2 exit 2 fi rtk dotnet "$@"
Type guard
rust:
fn has_dotnet_subcommand(args: &[std::ffi::OsString]) -> bool {
!args.is_empty()
} Try / catch
rust:
match dotnet::run_passthrough(&args, verbose) {
Err(e) if e.to_string().contains("dotnet: no subcommand specified") => {
eprintln!("usage: rtk dotnet <subcommand> [args...]");
std::process::exit(2);
}
result => result?,
} Prevention
- Always name the dotnet subcommand explicitly (build, test, run) when calling rtk
- Quote and check dynamically-built argument arrays before forwarding to rtk
- Prefer `rtk proxy dotnet` when you genuinely want the bare dotnet CLI behavior
When it happens
Trigger: Running `rtk dotnet` with zero arguments, which hits `args.is_empty()` at src/cmds/dotnet/dotnet_cmd.rs:80. Typical producers: a wrapper script or alias forwarding an unset/empty variable (`rtk dotnet $DOTNET_ARGS` with DOTNET_ARGS empty), or an agent tool-call that drops the subcommand.
Common situations: CI scripts that assemble dotnet arguments dynamically and forward an empty vector; shell functions with `set -u` disabled letting an empty var expand to nothing; typos like `rtk dotnet ''`; wrapper scripts around `rtk dotnet "$@"` invoked with no positional args.
Related errors
- go: no subcommand specified
- sbt: no subcommand specified
- gt: no subcommand specified
- --codex cannot be combined with --opencode
- --codex cannot be combined with --claude-md
AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16).
Data as JSON: /api/errors/bf8c8725aa0f4ef9.
Report an issue: GitHub.