Skip to content

[correctness/medium] JiraClient._request() retries once, crashes on non-numeric Retry-After, ignores 5xx and transport errors #70

Description

@tomharris

JiraClient._request() has three related gaps:

  1. Single retry, not a loop — a second consecutive 429 aborts the sync.
  2. Unguarded int() on Retry-After — raises ValueError on a non-numeric value. RFC 9110
    allows an HTTP-date here, so this is reachable, not theoretical.
  3. No 5xx or transport-error handling — both are already retried by SlackClient._call().

Location: devrag/utils/jira_client.py:36-43

Suggested fix:

Adopt the SlackClient._call() retry structure — a bounded loop with backoff, tolerant header
parsing, and httpx.TransportError handling:

    def _request(self, method: str, url: str, **kwargs) -> httpx.Response:
        for attempt in range(self._max_retries + 1):
            last = attempt == self._max_retries
            try:
                resp = self._client.request(method, url, **kwargs)
            except httpx.TransportError:
                if last:
                    raise
                time.sleep(self._backoff(attempt))
                continue
            if resp.status_code == 429 or resp.status_code >= 500:
                if last:
                    resp.raise_for_status()
                time.sleep(self._backoff(attempt, resp.headers.get("Retry-After")))
                continue
            break
        resp.raise_for_status()
        return resp

Given all three clients need the same behavior, consider extracting one shared retry helper into
devrag/utils/http.py rather than fixing each in isolation.

Source: Surfaced by /engineer-agent audit-code (June run); re-verified by hand against HEAD d97b2eb on 2026-07-15, confidence high.

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditSurfaced by /engineer-agent audit-codeaudit:correctnessAudit finding: correctness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions