{"record":{"id":"bbd0b205404d0168","repo":"zeroclaw-labs/zeroclaw","slug":"create-ticket-requires-a-non-empty-issue-type","errorCode":null,"errorMessage":"create_ticket requires a non-empty issue_type","messagePattern":"create_ticket requires a non-empty issue_type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/jira_tool.rs","lineNumber":851,"sourceCode":"    }\n\n    #[allow(clippy::too_many_arguments)]\n    async fn create_ticket(\n        &self,\n        project_key: &str,\n        issue_type: &str,\n        summary: &str,\n        description: Option<&str>,\n        assignee: Option<&str>,\n        labels: Option<&[String]>,\n        parent_key: Option<&str>,\n    ) -> anyhow::Result<ToolResult> {\n        validate_project_key(project_key)?;\n        if summary.trim().is_empty() {\n            anyhow::bail!(\"create_ticket requires a non-empty summary\");\n        }\n        if issue_type.trim().is_empty() {\n            anyhow::bail!(\"create_ticket requires a non-empty issue_type\");\n        }\n        if let Some(parent) = parent_key {\n            validate_issue_key(parent)?;\n        }\n\n        let mut fields = serde_json::Map::new();\n        fields.insert(\"project\".into(), json!({ \"key\": project_key }));\n        fields.insert(\"issuetype\".into(), json!({ \"name\": issue_type }));\n        fields.insert(\"summary\".into(), json!(summary));\n\n        if let Some(desc) = description {\n            let value = if self.is_cloud() {\n                build_adf(desc, &HashMap::new())\n            } else {\n                json!(desc)\n            };\n            fields.insert(\"description\".into(), value);\n        }","sourceCodeStart":833,"sourceCodeEnd":869,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/jira_tool.rs#L833-L869","documentation":"Client-side guard in create_ticket: after the summary check passes, an empty or whitespace-only issue_type aborts the call before any HTTP request. The issue_type is sent as {\"issuetype\":{\"name\":...}} in the create payload, so an empty name could never match a real type. Purely an input-validation error.","triggerScenarios":"Calling create_ticket with issue_type=\"\" or \"   \"; passing a user-provided category that is blank; wrappers defaulting a missing JSON field to an empty string instead of falling back to a sensible default like \"Task\".","commonSituations":"Configuration files mapping ticket kinds to Jira issue types with a missing/blank entry; LLM tool calls omitting issue_type; environments where the intended type name differs (\"Bug\" vs \"Incident\") and the caller sends nothing rather than guessing.","solutions":["Pass a real issue type name that exists in the target project (Task, Bug, Story, Epic, or a custom type).","Verify the exact spelling of custom issue types via the project's create-metadata in Jira UI or API.","Default to \"Task\" when the caller has no explicit type, or validate earlier in your layer."],"exampleFix":"// before\njira.create_ticket(\"PROJ\", \"\", \"Fix login crash\", None, None, None, None).await?; // -> error\n\n// after\njira.create_ticket(\"PROJ\", \"Bug\", \"Fix login crash\", None, None, None, None).await?;","handlingStrategy":"validation","validationCode":"let issue_type = issue_type.trim();\nif issue_type.is_empty() {\n    anyhow::bail!(\"issue_type required; valid types for this project: Task, Bug, Story\");\n}\njira.create_ticket(\"PROJ\", issue_type, summary, None, None, None, None).await?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make issue_type an enum in your calling code with the project's real types as variants.","Default to \"Task\" when the caller has no explicit type.","Verify custom type spellings against the project's issue-type list once at startup."],"tags":["jira","parameter-validation","create-ticket","issue-type"],"backgroundTag":"missing-required-field","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}