zeroclaw-labs/zeroclaw · error
Jira transition_ticket failed ({status}): {}
Error message
Jira transition_ticket failed ({status}): {} What it means
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.
Source
Thrown at crates/zeroclaw-tools/src/jira_tool.rs:814
.http
.post(&url)
.json(&body)
.timeout(std::time::Duration::from_secs(self.timeout_secs));
let resp = self.authenticated(req).send().await.map_err(|e| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"error": format!("{}", e)})),
"jira: Jira transition_ticket request failed"
);
anyhow::Error::msg(format!("Jira transition_ticket request failed: {e}"))
})?;
let status = resp.status();
if !status.is_success() {
let text = resp.text().await.unwrap_or_default();
anyhow::bail!(
"Jira transition_ticket failed ({status}): {}",
crate::util_helpers::truncate_with_ellipsis(&text, MAX_ERROR_BODY_CHARS)
);
}
// Jira returns 204 No Content on a successful transition.
let output = json!({
"ok": true,
"issue_key": issue_key,
"transition_id": resolved_id,
});
Ok(ToolResult {
success: true,
output: serde_json::to_string_pretty(&output)
.unwrap_or_else(|_| output.to_string())
.into(),
error: None,
})View on GitHub (pinned to 88bb9c8533)
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.
Example fix
// before
jira.transition_ticket("PROJ-42", Some(cached_id), None).await?; // cached_id stale after workflow edit
// after
// always resolve fresh at call time
let transitions = jira.list_transitions("PROJ-42").await?;
let id = /* find desired transition id in `transitions` */;
jira.transition_ticket("PROJ-42", Some(id), None).await?; Defensive patterns
Strategy: try-catch
Try / catch
// Stale-id race: one re-fetch + retry, then give up
match jira.transition_ticket(key, Some(&id), None).await {
Ok(_) => Ok(()),
Err(e) if e.to_string().starts_with("Jira transition_ticket failed (4") => {
// 4xx from Jira: id may be stale or blocked by a validator
let _ = jira.list_transitions(key).await?; // re-check availability
Err(e).context("transition rejected; re-inspect available transitions")
}
Err(e) => Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- statuses request returned {}
- Jira list_transitions failed ({status}): {}
- Transition '{name}' not found for {issue_key}. Available: {}
- Jira get_ticket failed ({status}): {}
- Jira search_tickets failed ({status}): {}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/542286763bf96799.
Report an issue: GitHub.