{"record":{"id":"3bb856f67a656625","repo":"zeroclaw-labs/zeroclaw","slug":"missing-worktree-path-parameter-for-worktree-rem","errorCode":null,"errorMessage":"Missing 'worktree_path' parameter for worktree remove","messagePattern":"Missing 'worktree_path' parameter for worktree remove","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/git_operations.rs","lineNumber":817,"sourceCode":"                    .unwrap_or_default();\n                // git worktree add <path> [<branch>]\n                let mut git_args = vec![\"worktree\", \"add\", worktree_path];\n                if !branch.is_empty() {\n                    self.sanitize_git_args(branch)?;\n                    git_args.push(branch);\n                }\n\n                self.run_git_command(&git_args, working_dir).await?;\n                Ok(ToolResult {\n                    success: true,\n                    output: format!(\"Worktree added at: {worktree_path}\").into(),\n                    error: None,\n                })\n            }\n            \"remove\" => {\n                let worktree_path = match args.get(\"worktree_path\").and_then(|v| v.as_str()) {\n                    Some(p) => p,\n                    None => anyhow::bail!(\"Missing 'worktree_path' parameter for worktree remove\"),\n                };\n                self.sanitize_git_args(worktree_path)?;\n                let worktree_path = self.ensure_worktree_remove_target_allowed(worktree_path)?;\n                let worktree_path = worktree_path.to_str().ok_or_else(|| {\n                    ::zeroclaw_log::record!(\n                        WARN,\n                        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)\n                            .with_outcome(::zeroclaw_log::EventOutcome::Failure),\n                        \"git_operations: worktree path not valid UTF-8\"\n                    );\n                    anyhow::Error::msg(\"Worktree path must be valid UTF-8 for git execution\")\n                })?;\n\n                self.run_git_command(&[\"worktree\", \"remove\", worktree_path], working_dir)\n                    .await?;\n                Ok(ToolResult {\n                    success: true,\n                    output: format!(\"Worktree removed: {worktree_path}\").into(),","sourceCodeStart":799,"sourceCodeEnd":835,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/git_operations.rs#L799-L835","documentation":"Inside git_worktree, the \"remove\" branch requires a 'worktree_path' string in the args; if missing or not a string, the tool bails with 'Missing 'worktree_path' parameter for worktree remove'. After this shape check, the path is sanitized and passed through ensure_worktree_remove_target_allowed, which restricts which worktrees may be removed — a safety gate against deleting directories outside the managed set. The bail here is purely about argument presence/type and fires only when subcommand == \"remove\".","triggerScenarios":"Calling {\"subcommand\": \"remove\"} with no 'worktree_path'; passing {\"worktree_path\": null} or a number; using a different key such as \"target\" or \"path\". Running \"list\" first and forgetting to copy the path from its output into the remove call.","commonSituations":"Cleanup scripts iterate a hardcoded branch list but forget the path mapping; an agent removes a worktree it created earlier but loses the path between turns; the path came from parsing `worktree list --porcelain` output and the extraction returned None, serializing to a missing key.","solutions":["Include the exact path string: {\"subcommand\": \"remove\", \"worktree_path\": \"/tmp/zc-feature\"}.","Derive the path from the immediately preceding \"list\" subcommand's porcelain output rather than reconstructing it by convention.","Confirm the key is 'worktree_path' and the value is a JSON string, not null.","Expect the follow-up policy check: the target must be an allowed worktree location, so remove paths you created through this tool."],"exampleFix":"// before\nlet args = serde_json::json!({ \"subcommand\": \"remove\" });\n// tool bails: Missing 'worktree_path' parameter for worktree remove\n\n// after\nlet args = serde_json::json!({ \"subcommand\": \"remove\", \"worktree_path\": \"/tmp/zc-feature\" });","handlingStrategy":"validation","validationCode":"fn build_worktree_remove(path: &str) -> Option<serde_json::Value> {\n    (!path.is_empty()).then(|| serde_json::json!({ \"subcommand\": \"remove\", \"worktree_path\": path }))\n}","typeGuard":"fn is_valid_worktree_remove_args(args: &serde_json::Value) -> bool {\n    args.get(\"subcommand\").and_then(|v| v.as_str()) == Some(\"remove\")\n        && args.get(\"worktree_path\").and_then(|v| v.as_str()).is_some()\n}","tryCatchPattern":"match tool_result {\n    Err(e) if e.to_string().contains(\"for worktree remove\") => {\n        // re-run \"list\", parse the porcelain path, and retry with it\n    }\n    other => other,\n}","preventionTips":["Always run subcommand \"list\" before remove and copy the path verbatim from its output.","Store the path returned at add time and reuse it at remove time instead of recomputing conventions.","Validate the key set ('subcommand' + 'worktree_path') with a shared helper before every worktree call."],"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"}