{"record":{"id":"2de47e46c72b550e","repo":"zeroclaw-labs/zeroclaw","slug":"unknown-stash-action-action-use-push-pop-li","errorCode":null,"errorMessage":"Unknown stash action: {action}. Use: push, pop, list, drop","messagePattern":"Unknown stash action: (.+?)\\. Use: push, pop, list, drop","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/git_operations.rs","lineNumber":689,"sourceCode":"            \"drop\" => {\n                let index_raw = args.get(\"index\").and_then(|v| v.as_u64()).unwrap_or(0);\n                let index = i32::try_from(index_raw).map_err(|_| {\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                            .with_attrs(::serde_json::json!({\"index\": index_raw})),\n                        \"git_operations: stash index too large\"\n                    );\n                    anyhow::Error::msg(format!(\"stash index too large: {index_raw}\"))\n                })?;\n                self.run_git_command(\n                    &[\"stash\", \"drop\", &format!(\"stash@{{{index}}}\")],\n                    working_dir,\n                )\n                .await\n            }\n            _ => anyhow::bail!(\"Unknown stash action: {action}. Use: push, pop, list, drop\"),\n        };\n\n        match output {\n            Ok(out) => Ok(ToolResult {\n                success: true,\n                output: out.into(),\n                error: None,\n            }),\n            Err(e) => Ok(ToolResult {\n                success: false,\n                output: ToolOutput::default(),\n                error: Some(format!(\"Stash {action} failed: {e}\")),\n            }),\n        }\n    }\n\n    fn parse_worktree_list(&self, output: &str) -> serde_json::Value {\n        let mut worktrees = Vec::new();","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/git_operations.rs#L671-L707","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet args = serde_json::json!({ \"action\": \"apply\", \"index\": 0 });\n// tool bails: Unknown stash action: apply. Use: push, pop, list, drop\n\n// after: apply is not exposed; pop restores and drops the entry\nlet args = serde_json::json!({ \"action\": \"pop\" });","handlingStrategy":"type-guard","validationCode":"fn build_stash_args(action: &str) -> Option<serde_json::Value> {\n    is_supported_stash_action(action).then(|| serde_json::json!({ \"action\": action }))\n}","typeGuard":"const STASH_ACTIONS: &[&str] = &[\"push\", \"pop\", \"list\", \"drop\"];\nfn is_supported_stash_action(action: &str) -> bool {\n    STASH_ACTIONS.contains(&action)\n}","tryCatchPattern":"match tool_result {\n    Err(e) if e.to_string().starts_with(\"Unknown stash action\") => {\n        // map the requested action to the closest supported one (apply -> pop) or reject\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["git","stash","unsupported-operation","validation","zeroclaw-tools"],"backgroundTag":"unsupported-operation","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}