πŸ”§ Error Fixes
Β· 1 min read

Go: Context Deadline Exceeded β€” How to Fix It


context deadline exceeded means an operation didn’t complete within the timeout set by context.WithTimeout or context.WithDeadline.

Why this happens

Go’s context package enforces deadlines to prevent operations from hanging indefinitely. When a network call, database query, or any blocking operation takes longer than the configured timeout, the context is cancelled and this error is returned. The timeout may be set explicitly in your code or inherited from a parent context higher in the call chain.

What causes this error

  1. HTTP request to slow server β€” the external API didn’t respond in time
  2. Database query too slow β€” complex query exceeds the context timeout
  3. Timeout too short β€” the default or configured timeout is too aggressive

Fix 1: Increase the timeout

// ❌ 1 second might be too short
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)

// βœ… Give it more time
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

Fix 2: Add timeout to HTTP clients

client := &http.Client{
    Timeout: 30 * time.Second,
}
resp, err := client.Get("https://slow-api.com/data")

Fix 3: Optimize the slow operation

If a database query is timing out, add indexes or simplify the query. If an API is slow, add caching or use a circuit breaker.

Alternative solutions

Retry with backoff: Use an exponential backoff strategy to retry failed requests rather than just increasing the timeout:

for i := 0; i < 3; i++ {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    resp, err := client.Do(req.WithContext(ctx))
    cancel()
    if err == nil { break }
    time.Sleep(time.Duration(i+1) * 2 * time.Second)
}

Use context.WithCancel for long-running operations and cancel manually when you detect the operation is no longer needed.

Prevention

  • Set realistic timeouts based on observed p99 latencies, not arbitrary values.
  • Always pass contexts through your call chain and always call defer cancel() to clean up resources.

Related: Go: Nil Pointer Dereference fix Β· Broken Pipe fix