go.unbounded_retry
Stability
High
Detects retry patterns that don’t have proper bounds, which can cause infinite loops on permanent failures.
Why It Matters
Section titled “Why It Matters”Unbounded retries cause:
- Infinite loops — Permanent failures never stop retrying
- Resource exhaustion — CPU and connections consumed by retries
- DoS on dependencies — Overwhelming already-struggling services
- Extended outages — Retries prevent recovery
Example
Section titled “Example”// ❌ Before (unbounded)func fetchData() error { for { if err := callAPI(); err == nil { return nil } time.Sleep(time.Second) }}// ✅ After (bounded with backoff)func fetchData() error { maxRetries := 5 backoff := time.Second
for i := 0; i < maxRetries; i++ { if err := callAPI(); err == nil { return nil } time.Sleep(backoff) backoff *= 2 // Exponential backoff if backoff > time.Minute { backoff = time.Minute } } return errors.New("max retries exceeded")}What Unfault Detects
Section titled “What Unfault Detects”for {}loops with retry patterns- Missing max retry count
- Missing backoff delays
- Retries without jitter
Auto-Fix
Section titled “Auto-Fix”Unfault generates patches using retry libraries:
import "github.com/cenkalti/backoff/v4"
func fetchData() error { operation := func() error { return callAPI() }
b := backoff.NewExponentialBackOff() b.MaxElapsedTime = 2 * time.Minute b.MaxInterval = 30 * time.Second
return backoff.Retry(operation, b)}