{"record":{"id":"39f79c6e589c23e3","repo":"Hmbown/CodeWhale","slug":"expected-workflow-tool-command","errorCode":null,"errorMessage":"expected workflow-tool command","messagePattern":"expected workflow-tool command","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":14972,"sourceCode":"            cli.command,\n            Some(Commands::Auth(TuiAuthArgs {\n                command: TuiAuthCommand::ChatgptRevoke\n            }))\n        ));\n    }\n\n    #[test]\n    fn workflow_tool_internal_subcommand_parses_exact_json() {\n        let cli = parse_cli(&[\n            \"codewhale-tui\",\n            \"workflow-tool\",\n            \"--approval-source\",\n            \"explicit-workflow-command\",\n            \"--input-json\",\n            r#\"{\"action\":\"run\",\"source_path\":\"workflows/demo.js\"}\"#,\n        ]);\n        let Some(Commands::WorkflowTool(args)) = cli.command else {\n            panic!(\"expected workflow-tool command\");\n        };\n        assert!(args.input_json.contains(\"\\\"action\\\":\\\"run\\\"\"));\n    }\n\n    #[tokio::test]\n    async fn direct_workflow_tool_runs_without_an_operator_model_turn() {\n        use crate::tools::spec::ToolSpec;\n\n        let workspace = tempfile::tempdir().expect(\"workspace\");\n        let config = Config {\n            provider: Some(\"vllm\".to_string()),\n            mcp_config_path: Some(\n                workspace\n                    .path()\n                    .join(\"missing-mcp.json\")\n                    .display()\n                    .to_string(),\n            ),","sourceCodeStart":14954,"sourceCodeEnd":14990,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/lib.rs#L14954-L14990","documentation":"A test-only panic in crates/tui/src/lib.rs:14972. The test calls parse_cli (a clap Cli::try_parse wrapper around the codewhale-tui CLI) and uses a let-else to destructure `Commands::WorkflowTool(args)`; if the parsed command is `None` or any other variant, the else branch panics with \"expected workflow-tool command\". It signals that the `workflow-tool` subcommand was not recognized or was shadowed by top-level flags.","triggerScenarios":"parse_cli(&[\"codewhale\",\"workflow-tool\",\"--approval-source\",\"explicit-workflow-command\",\"--input-json\",\"{...}\"]) returns a Cli whose `command` is not `Commands::WorkflowTool` — typically because the subcommand name changed, the hidden `#[command(name = \"workflow-tool\")]` rename was removed, or a global/flatten arg consumed the tokens so the subcommand parsed as None.","commonSituations":"Renaming the Commands enum variant or its clap `name` without updating tests; adding a top-level multi-value arg (like `prompt: Vec<String>` with num_args=1..) that swallows the subcommand; running the test after a conflict in FeatureToggles flatten flags.","solutions":["Confirm the `Commands::WorkflowTool` variant still exists with `#[command(name = \"workflow-tool\")]` in the Commands enum (crates/tui/src/lib.rs:328).","Print `cli.command` in the else branch (`panic!(\"expected workflow-tool command, got {:?}\", cli.command)`) to see what actually parsed.","Check whether new top-level flags (e.g. `--prompt` with num_args=1..) are intercepting the subcommand position; move them after the subcommand or mark them with `trailing_var_arg` semantics.","Update the test argv if the subcommand name was intentionally renamed."],"exampleFix":"// before\nlet Some(Commands::WorkflowTool(args)) = cli.command else {\n    panic!(\"expected workflow-tool command\");\n};\n// after\nlet Some(Commands::WorkflowTool(args)) = cli.command else {\n    panic!(\"expected workflow-tool command, got {:?}\", cli.command);\n};","handlingStrategy":"validation","validationCode":"// Before asserting, check the variant explicitly:\nmatch cli.command {\n    Some(Commands::WorkflowTool(ref args)) => assert!(args.input_json.contains(\"\\\"action\\\":\\\"run\\\"\")),\n    other => panic!(\"expected workflow-tool command, got {other:?}\"),\n}","typeGuard":"fn as_workflow_tool(cmd: &Option<Commands>) -> Option<&WorkflowToolArgs> {\n    match cmd { Some(Commands::WorkflowTool(a)) => Some(a), _ => None }\n}","tryCatchPattern":null,"preventionTips":["Keep hidden subcommand `#[command(name = ...)]` renames in sync with tests that reference them.","Give let-else panics `got {:?}` context so failures self-diagnose.","Run the focused test filter after every change to the Commands enum or Cli struct.","Avoid new top-level multi-value args that can swallow subcommand positions."],"tags":["rust","test-panic","cli-parsing","clap"],"backgroundTag":"internal-invariant-violation","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}