{"record":{"id":"bb48f2d75c34c444","repo":"zeroclaw-labs/zeroclaw","slug":"jira-allowed-actions-contains-unknown-action","errorCode":null,"errorMessage":"jira.allowed_actions contains unknown action: '{}'. Valid: get_ticket, search_tickets, comment_ticket, list_projects, myself, list_transitions, transition_ticket, create_ticket","messagePattern":"jira\\.allowed_actions contains unknown action: '(.+?)'\\. Valid: get_ticket, search_tickets, comment_ticket, list_projects, myself, list_transitions, transition_ticket, create_ticket","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":22089,"sourceCode":"                    .is_empty()\n            {\n                anyhow::bail!(\n                    \"jira.api_token must be set (or JIRA_API_TOKEN env var) when jira.enabled = true\"\n                );\n            }\n            let valid_actions = [\n                \"get_ticket\",\n                \"search_tickets\",\n                \"comment_ticket\",\n                \"list_projects\",\n                \"myself\",\n                \"list_transitions\",\n                \"transition_ticket\",\n                \"create_ticket\",\n            ];\n            for action in &self.jira.allowed_actions {\n                if !valid_actions.contains(&action.as_str()) {\n                    anyhow::bail!(\n                        \"jira.allowed_actions contains unknown action: '{}'. \\\n                         Valid: get_ticket, search_tickets, comment_ticket, list_projects, myself, list_transitions, transition_ticket, create_ticket\",\n                        action\n                    );\n                }\n            }\n        }\n\n        // Nevis IAM — delegate to NevisConfig::validate() for field-level checks\n        if let Err(msg) = self.security.nevis.validate() {\n            anyhow::bail!(\"security.nevis: {msg}\");\n        }\n\n        // Delegate tool global defaults\n        if self.delegate.timeout_secs == 0 {\n            validation_bail!(\n                InvalidNumericRange,\n                \"delegate.timeout_secs\",","sourceCodeStart":22071,"sourceCodeEnd":22107,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L22071-L22107","documentation":"Config::validate iterates jira.allowed_actions and rejects any entry not in the closed set of eight supported actions: get_ticket, search_tickets, comment_ticket, list_projects, myself, list_transitions, transition_ticket, create_ticket. The list exists to cap what the Jira tool may do, so unknown strings — including actions from newer/older ZeroClaw versions or plain typos — fail validation rather than being ignored. Matching is exact and case-sensitive.","triggerScenarios":"Writing an action with a typo (\"get-ticket\", \"search_ticket\", \"CreateTicket\"); listing an action that exists in another tool's vocabulary (\"delete_ticket\", \"update_ticket\"); downgrading ZeroClaw while keeping a config that uses an action added in the newer version; singular/plural mistakes (\"list_project\").","commonSituations":"Config authored against release notes of a different version; hand-merged configs where an action name got mangled; users assuming write actions beyond the eight exist.","solutions":["Correct the entry to one of: get_ticket, search_tickets, comment_ticket, list_projects, myself, list_transitions, transition_ticket, create_ticket (exact lowercase snake_case)","Remove the unsupported action if it is not needed","If the action genuinely should exist, upgrade ZeroClaw — the valid set grows across versions"],"exampleFix":"# before\n[jira]\nenabled = true\nallowed_actions = [\"get-ticket\", \"update_ticket\"]\n\n# after\n[jira]\nenabled = true\nallowed_actions = [\"get_ticket\", \"transition_ticket\"]","handlingStrategy":"type-guard","validationCode":"pub const JIRA_ACTIONS: [&str; 8] = [\n    \"get_ticket\", \"search_tickets\", \"comment_ticket\", \"list_projects\",\n    \"myself\", \"list_transitions\", \"transition_ticket\", \"create_ticket\",\n];\nfn jira_actions_ok(actions: &[String]) -> bool {\n    actions.iter().all(|a| JIRA_ACTIONS.contains(&a.as_str()))\n}","typeGuard":"fn is_valid_jira_action(action: &str) -> bool {\n    JIRA_ACTIONS.contains(&action)\n}\n\n// narrow before save:\nlet cleaned: Vec<String> = cfg.jira.allowed_actions.iter()\n    .filter(|a| is_valid_jira_action(a))\n    .cloned().collect();","tryCatchPattern":"match cfg.validate() {\n    Err(e) if e.to_string().starts_with(\"jira.allowed_actions\") => {\n        let bad: Vec<_> = cfg.jira.allowed_actions.iter()\n            .filter(|a| !is_valid_jira_action(a)).collect();\n        eprintln!(\"unknown jira actions {bad:?}; valid: {JIRA_ACTIONS:?}\");\n    }\n    other => other?,\n}","preventionTips":["Restrict UI/script inputs to a dropdown of the eight valid action ids","After upgrading ZeroClaw, re-validate configs that list actions — new versions may add or rename entries","Use exact snake_case; a lint rule (or grep in CI) for `allowed_actions = [` catches hand edits"],"tags":["jira","config","validation","enum","allowlist"],"backgroundTag":"invalid-enum-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}