{"record":{"id":"542286763bf96799","repo":"zeroclaw-labs/zeroclaw","slug":"jira-transition-ticket-failed-status","errorCode":null,"errorMessage":"Jira transition_ticket failed ({status}): {}","messagePattern":"Jira transition_ticket failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/jira_tool.rs","lineNumber":814,"sourceCode":"            .http\n            .post(&url)\n            .json(&body)\n            .timeout(std::time::Duration::from_secs(self.timeout_secs));\n        let resp = self.authenticated(req).send().await.map_err(|e| {\n            ::zeroclaw_log::record!(\n                ERROR,\n                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                    .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                    .with_attrs(::serde_json::json!({\"error\": format!(\"{}\", e)})),\n                \"jira: Jira transition_ticket request failed\"\n            );\n            anyhow::Error::msg(format!(\"Jira transition_ticket request failed: {e}\"))\n        })?;\n\n        let status = resp.status();\n        if !status.is_success() {\n            let text = resp.text().await.unwrap_or_default();\n            anyhow::bail!(\n                \"Jira transition_ticket failed ({status}): {}\",\n                crate::util_helpers::truncate_with_ellipsis(&text, MAX_ERROR_BODY_CHARS)\n            );\n        }\n\n        // Jira returns 204 No Content on a successful transition.\n        let output = json!({\n            \"ok\": true,\n            \"issue_key\": issue_key,\n            \"transition_id\": resolved_id,\n        });\n        Ok(ToolResult {\n            success: true,\n            output: serde_json::to_string_pretty(&output)\n                .unwrap_or_else(|_| output.to_string())\n                .into(),\n            error: None,\n        })","sourceCodeStart":796,"sourceCodeEnd":832,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/jira_tool.rs#L796-L832","documentation":"Thrown when POST {base_url}/rest/api/{ver}/issue/{key}/transitions returns a non-2xx status after the tool resolved a transition id and submitted {\"transition\":{\"id\":...}}. A 204 is the success path, so any error status (typically 400) means Jira rejected the transition itself. The truncated response body usually names the exact problem.","triggerScenarios":"Posting a transition id that is valid in the workflow but not available from the issue's current status (400 'transition is not valid'); racing another user/process that already moved the issue; transition ids fetched long ago that changed after a workflow edit; 401/403 when the user lacks transition permission.","commonSituations":"Automation caching transition ids across workflow updates; two automations transitioning the same issue concurrently; permissions schemes that allow viewing but not transitioning an issue; Jira Cloud workflow validators (e.g. required fields on transition) rejecting the POST.","solutions":["Read the Jira body in the message — 'It isn't possible to transition' style errors mean the id is stale; re-fetch with list_transitions and retry with a fresh id.","If a workflow validator demands fields, supply them via the Jira API directly or transition manually once to see the required inputs.","For 401/403, verify the token and the user's transition permission in the project's permission scheme.","Add concurrency protection (lock or re-check current status right before transitioning) when multiple writers touch the issue."],"exampleFix":"// before\njira.transition_ticket(\"PROJ-42\", Some(cached_id), None).await?; // cached_id stale after workflow edit\n\n// after\n// always resolve fresh at call time\nlet transitions = jira.list_transitions(\"PROJ-42\").await?;\nlet id = /* find desired transition id in `transitions` */;\njira.transition_ticket(\"PROJ-42\", Some(id), None).await?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Stale-id race: one re-fetch + retry, then give up\nmatch jira.transition_ticket(key, Some(&id), None).await {\n    Ok(_) => Ok(()),\n    Err(e) if e.to_string().starts_with(\"Jira transition_ticket failed (4\") => {\n        // 4xx from Jira: id may be stale or blocked by a validator\n        let _ = jira.list_transitions(key).await?; // re-check availability\n        Err(e).context(\"transition rejected; re-inspect available transitions\")\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Resolve the transition id immediately before the POST instead of caching ids.","Serialize transitions per issue when multiple automations can move it.","Read the Jira body: validator errors list required fields you can then supply."],"tags":["jira","http-status","workflow","transitions"],"backgroundTag":"http-error-response","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}