Hmbown/CodeWhale · error
expected exec command
Error message
expected exec command
What it means
Test-only panic in crates/tui/src/lib.rs:15430. The test `exec_accepts_split_prompt_words_for_windows_cmd_shims` parses ["codewhale","exec","hello","world"] and destructures `Commands::Exec(args)` via let-else; if parsing yields another variant or None, it panics with "expected exec command". The point under test is that unflagged words after `exec` stay in `args.prompt` instead of being absorbed elsewhere.
Solutions
- Verify `Commands::Exec(ExecArgs)` is still a declared subcommand in the Commands enum.
- Panic with the actual parsed value (`got {:?}`) to identify what clap produced instead.
- Ensure top-level multi-value args do not shadow the subcommand; clap only parses subcommands before free-standing positional values.
- Run `cargo test -p codewhale-tui --lib exec_accepts_split_prompt_words` after any Cli struct change.
Defensive patterns
Strategy: validation
Validate before calling
match cli.command {
Some(Commands::Exec(ref args)) => assert_eq!(args.prompt, vec!["hello", "world"]),
other => panic!("expected exec command, got {other:?}"),
} Type guard
fn as_exec(cmd: &Option<Commands>) -> Option<&ExecArgs> {
match cmd { Some(Commands::Exec(a)) => Some(a), _ => None }
} Prevention
- Never add an unbounded top-level positional/num_args=1.. arg above subcommands.
- Add debug context to destructuring panics in shared test helpers.
- After editing Cli/Commands, run the exec CLI test filter before committing.
When it happens
Trigger: parse_cli of `exec hello world` does not produce `Commands::Exec` — the `exec` subcommand was renamed/aliased away, or a new top-level argument captured "exec"/the prompt words so `cli.command` is None.
Common situations: Adding a global catch-all `prompt: Vec<String>` (num_args=1..) at the Cli level that eats "exec"; renaming `Commands::Exec`; breaking the subcommand dispatch while refactoring FeatureToggles.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- expected review command
- expected workflow-tool command
- cached read tool executes
- continue_goal with a wire-supplied schedule id still parses
- expected doctor command
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/1c5290161bc7fc99.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/lib.rs:15430
assert_eq!(execution.default_model(), "routed-legacy-model");
assert_eq!(execution.deepseek_base_url(), "http://127.0.0.1:18183/v1");
assert_eq!(execution.deepseek_api_key().unwrap(), "legacy-root-key");
for _ in 0..2 {
let identity = execution
.resolve_provider_identity("custom")
.expect("legacy identity remains repeatedly resolvable");
assert_eq!(identity.key, "custom");
}
let client =
crate::client::DeepSeekClient::new(&execution).expect("legacy execution client");
assert_eq!(client.base_url(), "http://127.0.0.1:18183/v1");
}
#[test]
fn exec_accepts_split_prompt_words_for_windows_cmd_shims() {
let cli = parse_cli(&["codewhale", "exec", "hello", "world"]);
let Some(Commands::Exec(args)) = cli.command else {
panic!("expected exec command");
};
assert_eq!(args.prompt, vec!["hello", "world"]);
}
#[test]
fn exec_keeps_model_flag_before_split_prompt_words() {
let cli = parse_cli(&["codewhale", "exec", "--model", "auto", "hello", "world"]);
let Some(Commands::Exec(args)) = cli.command else {
panic!("expected exec command");
};
assert_eq!(args.model.as_deref(), Some("auto"));
assert_eq!(args.prompt, vec!["hello", "world"]);
}
#[test]
fn exec_keeps_flags_before_split_prompt_words() {View on GitHub (pinned to 433685b202)