zeroclaw-labs/zeroclaw · error

Jira comment_ticket failed ({status}): {}

Error message

Jira comment_ticket failed ({status}): {}

What it means

POST {base_url}/rest/api/{2|3}/issue/{key}/comment answered non-2xx; the truncated body is inlined. This is reached only after the local allowed_actions gate permitted the comment action, so the failure is server-side: 403 the token user lacks Comment permission or the workflow blocks it, 400 invalid or empty body (v3 expects valid ADF content), 404 unknown issue, 401 credentials.

Source

Thrown at crates/zeroclaw-tools/src/jira_tool.rs:375

            .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 comment_ticket request failed"
            );
            anyhow::Error::msg(format!("Jira comment_ticket request failed: {e}"))
        })?;

        let status = resp.status();
        if !status.is_success() {
            let text = resp.text().await.unwrap_or_default();
            anyhow::bail!(
                "Jira comment_ticket failed ({status}): {}",
                crate::util_helpers::truncate_with_ellipsis(&text, MAX_ERROR_BODY_CHARS)
            );
        }

        let response: 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 comment response"
            );
            anyhow::Error::msg(format!("Failed to parse Jira comment response: {e}"))
        })?;

        let shaped = shape_comment_response(&response);
        Ok(ToolResult {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Read the status in the message: 403 -> grant the bot Add Comments permission on the project; 400 -> simplify and shorten the comment text; 404 -> verify the issue key
  2. Open the issue in the web UI and comment as the same bot user to see the exact restriction
  3. Confirm comment_ticket is in allowed_actions and the token user can browse the project
  4. If the workflow blocks comments in the current status, transition the issue first or relax the validator

Example fix

// before: empty comment body sneaks through to an HTTP 400
{"action": "comment_ticket", "ticket": "ACME-7", "comment": ""}

// after: guard the argument before invoking the tool
let comment = args["comment"].as_str().unwrap_or("").trim();
if comment.is_empty() {
    return Err(anyhow::anyhow!("comment must be non-empty"));
}
Defensive patterns

Strategy: validation

Validate before calling

// caller-side pre-check before comment_ticket
fn comment_args_valid(args: &serde_json::Value) -> bool {
    args.get("ticket").and_then(|v| v.as_str()).is_some_and(valid_issue_key)
        && args
            .get("comment")
            .and_then(|v| v.as_str())
            .is_some_and(|c| !c.trim().is_empty())
}

Type guard

fn is_jira_comment_http_failure(err: &anyhow::Error) -> bool {
    err.to_string().starts_with("Jira comment_ticket failed (")
}

Try / catch

match jira.execute(comment_args).await {
    Ok(res) => res,
    Err(e) if is_jira_comment_http_failure(&e) => {
        let msg = e.to_string();
        if msg.starts_with("Jira comment_ticket failed (403") {
            queue_for_human_review(&msg) // permission problem: do not retry
        } else {
            return Err(e)
        }
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: comment_ticket on an issue whose workflow validator forbids commenting or whose resolved screen rejects the body (400); a token user without the Add Comments project permission (403); commenting on an issue key that belongs to another site (404).

Common situations: Bot users added to projects as viewers only; comments attempted on closed issues in restricted workflows; agents composing very long or emoji-heavy comments that the v3 ADF conversion rejects; issues moved between projects breaking cached keys.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/8db77040601232de. Report an issue: GitHub.