rtk-ai/rtk · error
go: no subcommand specified
Error message
go: no subcommand specified
What it means
rtk's `go` proxy refuses to execute when invoked with no subcommand at all (e.g. bare `rtk go`). The filter layer needs at least one argument to decide which go subcommand to intercept and compress, so an empty argument list is rejected up front with anyhow::bail! in run_other.
Solutions
- Pass a go subcommand: `rtk go build ./...`, `rtk go test ./...`, `rtk go vet`.
- Check the script/wrapper for an empty variable that was supposed to hold the subcommand (e.g. `${GO_CMD:-}`) and guard against unset values.
- Use `rtk proxy go` if you truly want raw passthrough behavior of `go` with no subcommand.
- Call `go` directly (without rtk) when you only want go's own usage output.
Example fix
// before
rtk go $SUBCMD # SUBCMD unset -> go: no subcommand specified
// after
rtk go "${SUBCMD:-build}" ./... # or: [ -n "$SUBCMD" ] && rtk go "$SUBCMD" Defensive patterns
Strategy: validation
Validate before calling
if [ -z "$SUBCMD" ]; then echo "usage: rtk go <subcommand> [args]" >&2; exit 2; fi rtk go "$SUBCMD" "$@"
Type guard
fn has_args(args: &[OsString]) -> bool { !args.is_empty() } Try / catch
match rtk_result {
Err(e) if e.to_string().contains("no subcommand specified") => {
eprintln!("supply a go subcommand, e.g. rtk go build ./...");
std::process::exit(2);
}
other => other?,
} Prevention
- Never invoke `rtk go` with a potentially empty variable; use ${VAR:-default} or ${VAR:?msg}.
- Quote and validate all interpolated args in wrapper scripts.
- Prefer `rtk proxy go` when you want unfiltered pass-through of arbitrary go invocations.
When it happens
Trigger: Calling `rtk go` with zero trailing arguments, or programmatically dispatching to go_cmd::run_other(&[], verbose) with an empty OsString slice.
Common situations: Shell scripts that build a go command from variables where the subcommand variable is unset/empty (`rtk go $GO_CMD` with GO_CMD=""), wrappers that forward args incorrectly and drop them, or users typing `rtk go` expecting it to behave like `go` alone (which prints usage rather than failing).
Understand the failure class
Background: "no subcommand specified" and "... is required": CLI errors when a required argument is missing — this error's family across 13 libraries.
Related errors
- at least one of install_claude or install_opencode must be…
- dotnet: no subcommand specified
- gt: no subcommand specified
- npx requires a command argument
- proxy requires a command to execute Usage: rtk proxy
AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19).
Data as JSON: /api/errors/04f25d650526c0b4.
Report an issue: GitHub.
Appendix: source
Thrown at src/cmds/go/go_cmd.rs:129
cmd.arg(arg);
}
if verbose > 0 {
eprintln!("Running: go vet {}", args.join(" "));
}
runner::run_filtered(
cmd,
"go vet",
&args.join(" "),
filter_go_vet,
crate::core::runner::RunOptions::with_tee("go_vet"),
)
}
pub fn run_other(args: &[OsString], verbose: u8) -> Result<i32> {
if args.is_empty() {
anyhow::bail!("go: no subcommand specified");
}
// Intercept: `go tool <known>` invocations for filtered output
if let Some((tool, tool_args)) = match_go_tool(args) {
match tool {
GoTool::GolangciLint => return run_go_tool_golangci_lint(tool_args, verbose),
}
}
let timer = tracking::TimedExecution::start();
let subcommand = args[0].to_string_lossy();
let mut cmd = resolved_command("go");
cmd.arg(&*subcommand);
for arg in &args[1..] {
cmd.arg(arg);
}View on GitHub (pinned to 0924356b4c)