{"record":{"id":"7b84dc03c3cb4020","repo":"zeroclaw-labs/zeroclaw","slug":"missing-subcommand-parameter-use-list-add-re","errorCode":null,"errorMessage":"Missing 'subcommand' parameter. Use: list, add, remove, prune","messagePattern":"Missing 'subcommand' parameter\\. Use: list, add, remove, prune","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/git_operations.rs","lineNumber":762,"sourceCode":"                \"path\": &current_path,\n                \"branch\": if is_detached { \"HEAD\" } else { current_branch.as_str() },\n                \"head\": &current_head,\n                \"detached\": is_detached,\n                \"active\": current_path == workspace.as_ref()\n            }));\n        }\n\n        json!({ \"worktrees\": worktrees })\n    }\n\n    async fn git_worktree(\n        &self,\n        args: serde_json::Value,\n        working_dir: &std::path::Path,\n    ) -> anyhow::Result<ToolResult> {\n        let subcommand = match args.get(\"subcommand\").and_then(|v| v.as_str()) {\n            Some(cmd) => cmd,\n            None => anyhow::bail!(\"Missing 'subcommand' parameter. Use: list, add, remove, prune\"),\n        };\n\n        match subcommand {\n            \"list\" => {\n                let output = self\n                    .run_git_command(&[\"worktree\", \"list\", \"--porcelain\"], working_dir)\n                    .await?;\n                let parsed = self.parse_worktree_list(&output);\n                Ok(ToolResult {\n                    success: true,\n                    output: serde_json::to_string_pretty(&parsed)\n                        .unwrap_or_default()\n                        .into(),\n                    error: None,\n                })\n            }\n            \"add\" => {\n                let worktree_path = match args.get(\"worktree_path\").and_then(|v| v.as_str()) {","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/git_operations.rs#L744-L780","documentation":"The git worktree tool requires a 'subcommand' string in its JSON args and dispatches to \"list\", \"add\", \"remove\", or \"prune\". If args.get(\"subcommand\") is absent or not a string (null, number, object), it bails immediately with 'Missing 'subcommand' parameter. Use: list, add, remove, prune'. Unlike git_stash, there is no default value — the parameter is mandatory. This is an argument-shape error raised before any git process is spawned.","triggerScenarios":"Calling the worktree tool with args that omit the key entirely, e.g. {} or {\"path\": \"/tmp/wt\"}; passing a non-string JSON value such as {\"subcommand\": 1} or {\"subcommand\": null}; misspelling the key as \"sub_command\" or \"command\".","commonSituations":"A caller copies the arg shape from a different git sub-tool (which uses 'action' or 'paths') and forgets the tool-specific key; an agent assumes 'list' is the default; a refactor renames the key in one place but not the tool-call site; JSON built with serde_json::json! drops the key due to a conditional insert that evaluated false.","solutions":["Always include a string 'subcommand': one of \"list\", \"add\", \"remove\", \"prune\", e.g. {\"subcommand\": \"list\"}.","Check the exact key spelling — it is 'subcommand', singular, all lowercase.","If the key may be absent, default it in the caller before invoking: args[\"subcommand\"].take() or json!({\"subcommand\": \"list\", ...(args) }).","Log the outgoing args object when debugging tool-call construction to spot dropped keys."],"exampleFix":"// before\nlet args = serde_json::json!({});\n// tool bails: Missing 'subcommand' parameter. Use: list, add, remove, prune\n\n// after\nlet args = serde_json::json!({ \"subcommand\": \"list\" });","handlingStrategy":"validation","validationCode":"fn build_worktree_args(args: &serde_json::Value) -> Option<serde_json::Value> {\n    args.get(\"subcommand\")?.as_str()?;\n    Some(args.clone())\n}","typeGuard":"fn has_worktree_subcommand(args: &serde_json::Value) -> bool {\n    args.get(\"subcommand\").and_then(|v| v.as_str()).is_some()\n}","tryCatchPattern":"match tool_result {\n    Err(e) if e.to_string().contains(\"Missing 'subcommand' parameter\") => {\n        // default to \"list\" and retry once with a corrected args object\n    }\n    other => other,\n}","preventionTips":["Centralize worktree args construction in one builder function that always sets 'subcommand'.","Treat the tool's parameter schema (subcommand is required, no default) as authoritative over git CLI habits.","Add a unit test asserting every worktree call site emits the key."],"tags":["git","worktree","missing-parameter","validation","zeroclaw-tools"],"backgroundTag":"missing-required-parameter","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}