zeroclaw-labs/zeroclaw · error · anyhow::Error
Missing 'subcommand' parameter. Use: list, add, remove, prun
Error message
Missing 'subcommand' parameter. Use: list, add, remove, prune
What it means
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.
Source
Thrown at crates/zeroclaw-tools/src/git_operations.rs:762
"path": ¤t_path,
"branch": if is_detached { "HEAD" } else { current_branch.as_str() },
"head": ¤t_head,
"detached": is_detached,
"active": current_path == workspace.as_ref()
}));
}
json!({ "worktrees": worktrees })
}
async fn git_worktree(
&self,
args: serde_json::Value,
working_dir: &std::path::Path,
) -> anyhow::Result<ToolResult> {
let subcommand = match args.get("subcommand").and_then(|v| v.as_str()) {
Some(cmd) => cmd,
None => anyhow::bail!("Missing 'subcommand' parameter. Use: list, add, remove, prune"),
};
match subcommand {
"list" => {
let output = self
.run_git_command(&["worktree", "list", "--porcelain"], working_dir)
.await?;
let parsed = self.parse_worktree_list(&output);
Ok(ToolResult {
success: true,
output: serde_json::to_string_pretty(&parsed)
.unwrap_or_default()
.into(),
error: None,
})
}
"add" => {
let worktree_path = match args.get("worktree_path").and_then(|v| v.as_str()) {View on GitHub (pinned to 88bb9c8533)
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.
Example fix
// before
let args = serde_json::json!({});
// tool bails: Missing 'subcommand' parameter. Use: list, add, remove, prune
// after
let args = serde_json::json!({ "subcommand": "list" }); Defensive patterns
Strategy: validation
Validate before calling
fn build_worktree_args(args: &serde_json::Value) -> Option<serde_json::Value> {
args.get("subcommand")?.as_str()?;
Some(args.clone())
} Type guard
fn has_worktree_subcommand(args: &serde_json::Value) -> bool {
args.get("subcommand").and_then(|v| v.as_str()).is_some()
} Try / catch
match tool_result {
Err(e) if e.to_string().contains("Missing 'subcommand' parameter") => {
// default to "list" and retry once with a corrected args object
}
other => other,
} Prevention
- 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.
When it happens
Trigger: 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".
Common situations: 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.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Missing 'worktree_path' parameter for worktree add
- Missing 'worktree_path' parameter for worktree remove
- Unknown worktree subcommand: {subcommand}. Use: list, add, r
- Path not allowed: contains null byte
- Path not allowed: parent-directory traversal is not allowed
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/7b84dc03c3cb4020.
Report an issue: GitHub.