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

  1. Pass a go subcommand: `rtk go build ./...`, `rtk go test ./...`, `rtk go vet`.
  2. Check the script/wrapper for an empty variable that was supposed to hold the subcommand (e.g. `${GO_CMD:-}`) and guard against unset values.
  3. Use `rtk proxy go` if you truly want raw passthrough behavior of `go` with no subcommand.
  4. 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

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


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)