go.http_missing_timeout
Stability
High
Common in Incidents
Detects HTTP client usage without explicit timeout configuration.
Why It Matters
Section titled “Why It Matters”HTTP requests without timeouts can hang indefinitely:
- Connection pool exhaustion — Stuck requests hold connections
- Goroutine leaks — Waiting goroutines accumulate
- Cascade failures — One slow upstream brings down your service
- Unresponsive service — All workers blocked waiting
The default http.Client has no timeout. This is a dangerous default.
Example
Section titled “Example”// ❌ Beforeclient := &http.Client{}resp, err := client.Get(url)
// Also bad: using http.Get directlyresp, err := http.Get(url)If the server never responds, these calls wait forever.
// ✅ Afterclient := &http.Client{ Timeout: 30 * time.Second,}resp, err := client.Get(url)After 30 seconds, the request fails with a timeout error.
What Unfault Detects
Section titled “What Unfault Detects”&http.Client{}without Timeout fieldhttp.Get(),http.Post(), etc. (use default client)- Client with Transport but no timeout
- Missing context deadline on requests
Auto-Fix
Section titled “Auto-Fix”Unfault can add Timeout: 30 * time.Second to HTTP client initialization when configuring a default client.
Best Practices
Section titled “Best Practices”// Overall request timeoutclient := &http.Client{ Timeout: 30 * time.Second,}
// Fine-grained control with Transportclient := &http.Client{ Timeout: 30 * time.Second, Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: 5 * time.Second, // Connection timeout KeepAlive: 30 * time.Second, }).DialContext, TLSHandshakeTimeout: 5 * time.Second, ResponseHeaderTimeout: 10 * time.Second, IdleConnTimeout: 90 * time.Second, },}
// Context-based timeout (per-request)ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)resp, err := client.Do(req)