zeroclaw-labs/zeroclaw · error
transition_ticket requires exactly one of transition_id or t
Error message
transition_ticket requires exactly one of transition_id or transition_name
What it means
Thrown by transition_ticket when neither a usable transition_id nor transition_name was supplied: the match arm falls through to the error when both are None or both are empty/whitespace-only strings. Despite the wording 'exactly one', if both are provided the non-empty transition_id silently wins; the error only fires when there is nothing to act on. No network request is made.
Source
Thrown at crates/zeroclaw-tools/src/jira_tool.rs:782
None
}
});
match found {
Some(id) => id,
None => {
let available: Vec<&str> = transitions
.iter()
.filter_map(|t| t["name"].as_str())
.collect();
anyhow::bail!(
"Transition '{name}' not found for {issue_key}. Available: {}",
available.join(", ")
);
}
}
}
_ => {
anyhow::bail!(
"transition_ticket requires exactly one of transition_id or transition_name"
);
}
};
let ver = self.api_version();
let url = format!(
"{}/rest/api/{}/issue/{}/transitions",
self.base_url, ver, issue_key
);
let body = json!({ "transition": { "id": resolved_id } });
let req = self
.http
.post(&url)
.json(&body)
.timeout(std::time::Duration::from_secs(self.timeout_secs));
let resp = self.authenticated(req).send().await.map_err(|e| {View on GitHub (pinned to 88bb9c8533)
Solutions
- Pass a non-empty transition_id or transition_name (trim whitespace first).
- If your caller has optional values, default to empty-string handling: pass None rather than "" so intent is explicit.
- Validate arguments before dispatching the tool call (see defense below).
- When both are known, pass only transition_id to make intent unambiguous.
Example fix
// before
jira.transition_ticket("PROJ-42", Some(""), Some("")).await?; // -> error
// after
let name = "In Progress";
jira.transition_ticket("PROJ-42", None, Some(name)).await?; Defensive patterns
Strategy: validation
Validate before calling
// Reject before dispatch: require exactly one selector
fn valid_transition_args(id: Option<&str>, name: Option<&str>) -> bool {
let has_id = id.map(|s| !s.trim().is_empty()).unwrap_or(false);
let has_name = name.map(|s| !s.trim().is_empty()).unwrap_or(false);
has_id ^ has_name // exactly one
} Prevention
- Validate tool-call arguments at the boundary before invoking execute.
- Normalize empty strings to None so absence is explicit.
- Prefer transition_id in automation; keep transition_name for interactive flows.
When it happens
Trigger: Calling transition_ticket with transition_id=None and transition_name=None; passing Some("") or Some(" ") for both parameters (empty strings are treated as absent); building args from optional JSON fields that were omitted in the tool call.
Common situations: LLM/tool-caller omitting both fields when invoking the jira tool action; a wrapper mapping missing request fields to empty strings instead of None; refactoring that renamed the parameters and left callers passing neither.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Jira list_transitions failed ({status}): {}
- Transition '{name}' not found for {issue_key}. Available: {}
- Jira transition_ticket failed ({status}): {}
- create_ticket requires a non-empty summary
- create_ticket requires a non-empty issue_type
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/c69ad23af9dc1c5a.
Report an issue: GitHub.