zeroclaw-labs/zeroclaw · error · anyhow::Error
Unknown worktree subcommand: {subcommand}. Use: list, add, r
Error message
Unknown worktree subcommand: {subcommand}. Use: list, add, remove, prune What it means
The git worktree tool's subcommand match covers exactly "list", "add", "remove", and "prune"; any other string falls through to the bail 'Unknown worktree subcommand: {subcommand}. Use: list, add, remove, prune'. This is a vocabulary restriction relative to the git CLI, which also supports lock, unlock, move, and repair — those are intentionally not exposed by this tool. The check is case-sensitive and runs after the missing-parameter check, so the value is guaranteed to be a non-empty string here.
Source
Thrown at crates/zeroclaw-tools/src/git_operations.rs:848
self.run_git_command(&["worktree", "remove", worktree_path], working_dir)
.await?;
Ok(ToolResult {
success: true,
output: format!("Worktree removed: {worktree_path}").into(),
error: None,
})
}
"prune" => {
self.run_git_command(&["worktree", "prune"], working_dir)
.await?;
Ok(ToolResult {
success: true,
output: "Worktree prune completed".to_string().into(),
error: None,
})
}
_ => anyhow::bail!(
"Unknown worktree subcommand: {subcommand}. Use: list, add, remove, prune"
),
}
}
}
#[async_trait]
impl Tool for GitOperationsTool {
fn name(&self) -> &str {
"git_operations"
}
fn description(&self) -> &str {
"Perform structured Git operations (status, diff, log, branch, commit, add, checkout, stash, worktree). Provides parsed JSON output and integrates with security policy for autonomy controls."
}
fn parameters_schema(&self) -> serde_json::Value {
json!({View on GitHub (pinned to 88bb9c8533)
Solutions
- Use exactly one of: list, add, remove, prune (lowercase).
- For lock/unlock/move/repair, fall back to invoking git directly through a shell tool if your policy allows it — this tool will not grow them via argument tricks.
- For removing a worktree, the supported spelling is "remove" (not "rm" or "delete").
- When enumerating capabilities programmatically, treat the error's listed vocabulary as the schema of record.
Example fix
// before
let args = serde_json::json!({ "subcommand": "lock", "worktree_path": "/tmp/zc-feature" });
// tool bails: Unknown worktree subcommand: lock. Use: list, add, remove, prune
// after: lock/move are not exposed; remove is the supported cleanup path
let args = serde_json::json!({ "subcommand": "remove", "worktree_path": "/tmp/zc-feature" }); Defensive patterns
Strategy: type-guard
Validate before calling
fn build_worktree_args(subcommand: &str, path: Option<&str>) -> Option<serde_json::Value> {
WORKTREE_SUBCOMMANDS.contains(&subcommand).then(|| {
let mut args = serde_json::json!({ "subcommand": subcommand });
if let Some(p) = path { args["worktree_path"] = serde_json::json!(p); }
args
})
} Type guard
const WORKTREE_SUBCOMMANDS: &[&str] = &["list", "add", "remove", "prune"];
fn is_supported_worktree_subcommand(cmd: &str) -> bool {
WORKTREE_SUBCOMMANDS.contains(&cmd)
} Try / catch
match tool_result {
Err(e) if e.to_string().starts_with("Unknown worktree subcommand") => {
// the subcommand exists in git but not here; route lock/unlock/move to a shell tool or reject
}
other => other,
} Prevention
- Restrict your UI/agent schema to the four exposed subcommands; do not proxy raw git vocabulary.
- Map common shorthands before calling: rm->remove, new->add.
- Keep an allowlist constant in the caller synced with the error text's vocabulary.
When it happens
Trigger: Calling with {"subcommand": "lock"}, {"subcommand": "unlock"}, {"subcommand": "move"}, or {"subcommand": "repair"} — valid git worktree subcommands the tool does not implement. Also typos and case variants: "List", "rm", "delete", "prune " with trailing space (trailing spaces make it a different string, though leading/trailing whitespace inside the JSON string is not trimmed).
Common situations: A developer ports a workflow that relied on `git worktree lock` before a backup; an agent infers subcommands from git's man page instead of the tool's schema; scripted cleanup tries "rm" as a shorthand for remove.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unknown stash action: {action}. Use: push, pop, list, drop
- Missing 'subcommand' parameter. Use: list, add, remove, prun
- Missing 'worktree_path' parameter for worktree add
- Missing 'worktree_path' parameter for worktree remove
- Path not allowed: contains null byte
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/6459a8ec7e8788f3.
Report an issue: GitHub.