zeroclaw-labs/zeroclaw · error · anyhow::Error
Unknown stash action: {action}. Use: push, pop, list, drop
Error message
Unknown stash action: {action}. Use: push, pop, list, drop What it means
The git stash tool reads the optional 'action' string (defaulting to "push") and dispatches on it: "push" and "save" run stash push (with optional message, keep_index, include_untracked, paths), "pop", "list", and "drop" (with an 'index' number) map to their git counterparts. Any other value falls through to the bail 'Unknown stash action: {action}. Use: push, pop, list, drop'. The match is case-sensitive and the action must be a JSON string. Note the accepted alias "save" is not listed in the error text.
Source
Thrown at crates/zeroclaw-tools/src/git_operations.rs:689
"drop" => {
let index_raw = args.get("index").and_then(|v| v.as_u64()).unwrap_or(0);
let index = i32::try_from(index_raw).map_err(|_| {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"index": index_raw})),
"git_operations: stash index too large"
);
anyhow::Error::msg(format!("stash index too large: {index_raw}"))
})?;
self.run_git_command(
&["stash", "drop", &format!("stash@{{{index}}}")],
working_dir,
)
.await
}
_ => anyhow::bail!("Unknown stash action: {action}. Use: push, pop, list, drop"),
};
match output {
Ok(out) => Ok(ToolResult {
success: true,
output: out.into(),
error: None,
}),
Err(e) => Ok(ToolResult {
success: false,
output: ToolOutput::default(),
error: Some(format!("Stash {action} failed: {e}")),
}),
}
}
fn parse_worktree_list(&self, output: &str) -> serde_json::Value {
let mut worktrees = Vec::new();View on GitHub (pinned to 88bb9c8533)
Solutions
- Use one of the four supported actions: push, pop, list, or drop (lowercase, exact).
- For 'apply' semantics, use "pop" — it restores the stash and drops it, which is the closest supported behavior (there is no restore-without-drop here).
- To inspect stashes, use "list" and read the output instead of "show".
- Omit 'action' entirely when you want the default "push" behavior.
Example fix
// before
let args = serde_json::json!({ "action": "apply", "index": 0 });
// tool bails: Unknown stash action: apply. Use: push, pop, list, drop
// after: apply is not exposed; pop restores and drops the entry
let args = serde_json::json!({ "action": "pop" }); Defensive patterns
Strategy: type-guard
Validate before calling
fn build_stash_args(action: &str) -> Option<serde_json::Value> {
is_supported_stash_action(action).then(|| serde_json::json!({ "action": action }))
} Type guard
const STASH_ACTIONS: &[&str] = &["push", "pop", "list", "drop"];
fn is_supported_stash_action(action: &str) -> bool {
STASH_ACTIONS.contains(&action)
} Try / catch
match tool_result {
Err(e) if e.to_string().starts_with("Unknown stash action") => {
// map the requested action to the closest supported one (apply -> pop) or reject
}
other => other,
} Prevention
- Model the action as a closed enum in your calling code instead of a free string.
- Lowercase and trim user input before mapping it onto the four supported actions.
- Remember 'save' is a hidden alias for push; do not rely on it since the error text does not advertise it.
When it happens
Trigger: Calling stash with {"action": "apply"} (git supports it, this tool does not), {"action": "show"}, {"action": "branch"}, {"action": "clear"}, or a case typo like {"action": "Push"}. Also any non-string JSON value for 'action' would fail the as_str() and fall back to the default, so numeric actions never reach this error.
Common situations: A developer ports a shell workflow that used `git stash apply` or `git stash show` and assumes full git subcommand coverage; an agent guesses the action vocabulary from git's CLI instead of the tool's schema; case mismatch from user input passed through unnormalized.
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 worktree subcommand: {subcommand}. Use: list, add, r
- Commit message cannot be empty
- No paths to stage
- Invalid branch specification
- Missing 'subcommand' parameter. Use: list, add, remove, prun
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/2de47e46c72b550e.
Report an issue: GitHub.