{"record":{"id":"0727a15b06376212","repo":"rtk-ai/rtk","slug":"sbt-no-subcommand-specified","errorCode":null,"errorMessage":"sbt: no subcommand specified","messagePattern":"sbt: no subcommand specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmds/scala/sbt_cmd.rs","lineNumber":128,"sourceCode":"        RunOptions::with_tee(tee_label),\n    )\n}\n\npub fn run_test(args: &[String], verbose: u8) -> Result<i32> {\n    run_task(args, \"test\", filter_sbt_test, \"sbt_test\", verbose)\n}\n\npub fn run_compile(args: &[String], verbose: u8) -> Result<i32> {\n    run_task(args, \"compile\", filter_sbt_compile, \"sbt_compile\", verbose)\n}\n\npub fn run_run(args: &[String], verbose: u8) -> Result<i32> {\n    run_task(args, \"run\", filter_sbt_run, \"sbt_run\", verbose)\n}\n\npub fn run_other(args: &[OsString], verbose: u8) -> Result<i32> {\n    if args.is_empty() {\n        anyhow::bail!(\"sbt: no subcommand specified\");\n    }\n\n    let subcommand = args[0].to_string_lossy().into_owned();\n\n    // Integration test commands (it:test, IntegrationTest/test, etc.) produce standard\n    // ScalaTest output — filter them like `sbt test`, through the shared runner so the\n    // never_worse cap and tee hint apply (an unrecognized output would otherwise be\n    // reprinted verbatim plus the hint, i.e. more than the raw command produced).\n    if is_integration_test_cmd(&subcommand) || is_test_task(&subcommand) {\n        let mut cmd = resolved_command(\"sbt\");\n        cmd.arg(&subcommand);\n        for arg in &args[1..] {\n            cmd.arg(arg);\n        }\n\n        if verbose > 0 {\n            eprintln!(\"Running: sbt {} ...\", subcommand);\n        }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/rtk-ai/rtk/blob/d977e1c31621fe8704e6500ceeb9c7a0de2b6836/src/cmds/scala/sbt_cmd.rs#L110-L146","documentation":"RTK's sbt handler run_other requires a task name and bails on an empty args slice. Named tasks (compile, run, test variants) go through filtered runners; an empty invocation names no task and cannot be proxied to sbt meaningfully.","triggerScenarios":"Running `rtk sbt` with zero arguments (src/cmds/scala/sbt_cmd.rs:129). Also `rtk sbt $SBT_TASK` with SBT_TASK empty, or wrappers invoked without positionals.","commonSituations":"Build scripts parameterizing the sbt task that end up empty in some matrix leg; agents probing `rtk sbt` for a help screen; copy-pasted commands missing the task.","solutions":["Pass a task: `rtk sbt compile`, `rtk sbt test`, or an integration variant like `rtk sbt it:test` (routed through the shared test filter)","Use `rtk proxy sbt` for sbt's own interactive/bare behavior","Assert non-empty task in scripts before invoking rtk"],"exampleFix":"# before\nrtk sbt               # bail!(\"sbt: no subcommand specified\")\n\n# after\nrtk sbt 'testOnly com.example.FooSpec'\nrtk sbt it:test       # detected as integration test, filtered like sbt test","handlingStrategy":"validation","validationCode":"bash:\nif [ $# -eq 0 ]; then\n  echo \"usage: rtk sbt <task> [args...]\" >&2\n  exit 2\nfi\nrtk sbt \"$@\"","typeGuard":"rust:\nfn has_sbt_task(args: &[std::ffi::OsString]) -> bool {\n    !args.is_empty()\n}","tryCatchPattern":"rust:\nif let Err(e) = sbt_cmd::run_other(&args, verbose) {\n    if e.to_string().contains(\"sbt: no subcommand specified\") {\n        eprintln!(\"usage: rtk sbt <task> (compile | test | it:test | ...)\");\n        std::process::exit(2);\n    }\n    return Err(e);\n}","preventionTips":["Name the sbt task explicitly (compile, test, 'testOnly Foo')","Verify matrix-leg variables that select the task are set before invoking rtk","Use `rtk proxy sbt` for sbt's interactive shell instead of bare `rtk sbt`"],"tags":["sbt","scala","cli","usage","argument-validation"],"backgroundTag":null,"analyzedSha":"d977e1c31621fe8704e6500ceeb9c7a0de2b6836","analyzedAt":"2026-08-16T05:40:46.291Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}