zeroclaw-labs/zeroclaw · error
Jira get_ticket failed ({status}): {}
Error message
Jira get_ticket failed ({status}): {} What it means
Raised when GET {base_url}/rest/api/{2 or 3}/issue/{issue_key} answers non-2xx; the response body (truncated to 500 chars via truncate_with_ellipsis) is appended to the message. JiraTool picks API v3 + HTTP Basic (email:api_token) for Jira Cloud and v2 + Bearer PAT for Server/Data Center, so both wrong credentials and wrong deployment-type configuration surface here. Common statuses: 401 bad credentials, 404 issue missing or not visible to the token user, 403 no Browse permission.
Source
Thrown at crates/zeroclaw-tools/src/jira_tool.rs:127
.http
.get(&url)
.query(&query)
.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 get_ticket request failed"
);
anyhow::Error::msg(format!("Jira get_ticket request failed: {e}"))
})?;
let status = resp.status();
if !status.is_success() {
let text = resp.text().await.unwrap_or_default();
anyhow::bail!(
"Jira get_ticket failed ({status}): {}",
crate::util_helpers::truncate_with_ellipsis(&text, MAX_ERROR_BODY_CHARS)
);
}
let raw: Value = resp.json().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: Failed to parse Jira get_ticket response"
);
anyhow::Error::msg(format!("Failed to parse Jira get_ticket response: {e}"))
})?;
let shaped = match level {
LevelOfDetails::Basic => shape_basic(&raw),View on GitHub (pinned to 88bb9c8533)
Solutions
- Run the myself action with the same credentials first - a 401 there pinpoints bad auth, while 404 here means a missing or hidden issue
- Verify the issue key opens in the web UI of exactly that site
- Check the API token at id.atlassian.com (Security -> API tokens) and re-create it if revoked
- For Jira Cloud set BOTH email and API token; for Server/DC set NEITHER so the Bearer PAT path (v2) is used
- Confirm base_url is the site root, e.g. https://yoursite.atlassian.net, with no /rest suffix
Example fix
// before: Jira Cloud configured without email -> v2 + Bearer -> 401/404
JiraTool::new(
"https://acme.atlassian.net".into(),
None, // email missing: tool switches to Server/DC mode
personal_token,
actions,
security,
30,
)
// after: Cloud needs the account email -> v3 + Basic(email:token)
JiraTool::new(
"https://acme.atlassian.net".into(),
Some("dev@acme.com".into()),
api_token,
actions,
security,
30,
) Defensive patterns
Strategy: try-catch
Validate before calling
// validate the issue key before spending a round trip
fn valid_issue_key(k: &str) -> bool {
let mut parts = k.splitn(2, '-');
matches!((parts.next(), parts.next()),
(Some(p), Some(n))
if !p.is_empty()
&& p.chars().all(|c| c.is_ascii_alphanumeric())
&& !n.is_empty()
&& n.chars().all(|c| c.is_ascii_digit()))
} Type guard
fn is_jira_get_ticket_http_failure(err: &anyhow::Error) -> bool {
err.to_string().starts_with("Jira get_ticket failed (")
} Try / catch
match jira.execute(get_ticket_args).await {
Ok(res) => res,
Err(e) if is_jira_get_ticket_http_failure(&e) => {
let msg = e.to_string();
if msg.starts_with("Jira get_ticket failed (404") {
report_issue_not_found(&msg) // missing or not browsable
} else if msg.starts_with("Jira get_ticket failed (401") {
fix_credentials(&msg) // email/token/base_url mismatch
} else {
return Err(e)
}
}
Err(e) => return Err(e),
} Prevention
- Preflight credentials with the myself action once at startup
- Keep one config source of truth for base_url/email/token and derive Cloud-vs-Server from it
- Trim whitespace when loading tokens - never paste with a trailing newline
- Map project key prefixes to site names in docs so agents query the right instance
When it happens
Trigger: get_ticket on a key that does not exist in the configured site, belongs to a project the token user cannot browse (Jira answers 404 for hidden issues), or any call made while email/api_token/base_url are mismatched - for example omitting the email on Cloud so v2 + Bearer is sent where Basic is required.
Common situations: base_url typos (wrong site slug in https://yoursite.atlassian.net); revoked or expired Atlassian API tokens; PAT-on-Cloud or email-on-Server mix-ups because api_version() is chosen purely by email presence; issue keys typo'd or the issue moved/deleted.
Related errors
- Jira list_projects failed ({status}): {}
- Jira myself failed ({status}): {}
- Jira search_tickets failed ({status}): {}
- Jira comment_ticket failed ({status}): {}
- Jira list_projects users failed ({status}): {}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/943f9743bda656ac.
Report an issue: GitHub.