go.context_background
Stability
Medium
Detects inappropriate use of context.Background() where a proper context should be passed.
Why It Matters
Section titled “Why It Matters”Context carries cancellation, deadlines, and request-scoped values:
- Lost cancellation — Parent cancellation doesn’t propagate
- Leaked resources — Operations continue after request ended
- No deadline propagation — Request deadline ignored
- Missing tracing — Request tracing lost
Using context.Background() breaks the context chain that enables Go’s graceful shutdown and timeout patterns.
Example
Section titled “Example”// ❌ Beforefunc (s *Service) GetUser(ctx context.Context, id string) (*User, error) { // ctx ignored, context.Background() used instead return s.db.QueryContext(context.Background(), "SELECT...", id)}If the caller’s context is cancelled, the database query continues running.
// ✅ Afterfunc (s *Service) GetUser(ctx context.Context, id string) (*User, error) { return s.db.QueryContext(ctx, "SELECT...", id)}Now cancellation and deadlines propagate correctly.
What Unfault Detects
Section titled “What Unfault Detects”context.Background()when a context parameter is availablecontext.TODO()in production code (meant for development)- HTTP handlers not passing request context
- gRPC handlers ignoring the context parameter
Auto-Fix
Section titled “Auto-Fix”Unfault replaces context.Background() with the available context parameter.
When Background Is Acceptable
Section titled “When Background Is Acceptable”// Main function initializationfunc main() { ctx := context.Background() server.Start(ctx)}
// Long-running background jobsfunc StartBackgroundWorker() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() runWorker(ctx)}
// Testsfunc TestSomething(t *testing.T) { ctx := context.Background() // ...}Best Practices
Section titled “Best Practices”// HTTP handlers: use request contextfunc (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) { user, err := h.service.GetUser(r.Context(), userID)}
// gRPC handlers: context is first parameterfunc (s *server) GetUser(ctx context.Context, req *pb.Request) (*pb.Response, error) { return s.service.GetUser(ctx, req.Id)}
// Chain context through all callsfunc (s *Service) GetUser(ctx context.Context, id string) (*User, error) { user, err := s.cache.Get(ctx, id) if err != nil { user, err = s.db.Query(ctx, id) } return user, err}