#19540: feat: add timeout and exponential backoff retry for frontend API calls
app: web-ui
size: M
Cluster:
Error Resilience and Retry Logic
## Summary
- Add `resilientFetch()` wrapper (`ui/src/ui/resilient-fetch.ts`)
- Configurable timeout via AbortController (default: 30s)
- Exponential backoff retry with jitter (default: 3 attempts, 1-10s delay)
- Only retries on network errors and 5xx server responses
- 4xx client errors are NOT retried
- Respects caller's AbortSignal
## Test plan
- [x] Unit tests for successful first attempt
- [x] Test 4xx errors are not retried
- [x] Test 5xx errors trigger retry
- [x] Test network errors trigger retry
- [x] Test exhausted retries throw
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds a `resilientFetch()` wrapper with timeout and exponential backoff retry for frontend API calls. The implementation correctly handles timeouts (30s default), implements exponential backoff with jitter, and appropriately distinguishes between retryable (5xx, network errors) and non-retryable (4xx) failures. The AbortSignal merging logic properly respects caller aborts.
**Issues found:**
- Critical: when 5xx retries are exhausted, throws `Error` instead of returning the final `Response`, preventing callers from inspecting status/body
- Missing test coverage for exhausted 5xx retries scenario
<h3>Confidence Score: 3/5</h3>
- Safe to merge after addressing the 5xx response handling issue
- The implementation is well-structured with solid retry logic and signal handling, but has a logical issue where 5xx responses aren't properly returned after retry exhaustion. This could break error handling in production.
- Pay close attention to `ui/src/ui/resilient-fetch.ts` lines 91-92 and 112 for the response handling fix
<sub>Last reviewed commit: a72c5e7</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#12995: feat(infra): Add retry with exponential backoff for transient failures
by trevorgordon981 · 2026-02-10
78.2%
#23497: feat(retry): add retryHttpAsync utility with comprehensive coverage
by thinstripe · 2026-02-22
78.1%
#23745: fix(resilience): add timeout to unguarded fetch calls in browser su...
by kevinWangSheng · 2026-02-22
77.5%
#4086: Test/add backoff tests
by TechWizard9999 · 2026-01-29
77.3%
#16195: feat(infra): add unified retry utility with exponential backoff
by bianbiandashen · 2026-02-14
76.1%
#11874: fix: handle fetch rejections in provider usage withTimeout
by Zjianru · 2026-02-08
74.9%
#11472: fix: retry media fetch on transient network errors
by openclaw-quenio · 2026-02-07
74.3%
#7247: fix(telegram): abort stale getUpdates connections after long-poll t...
by JanderV · 2026-02-02
73.9%
#11101: fix: handle AbortError and WebSocket 1006 in unhandled rejection ha...
by Nipurn123 · 2026-02-07
73.3%
#23152: feat(plugin): add retry-backoff extension
by cintia09 · 2026-02-22
73.1%