go concurrency_error ai_generated true

goroutine leak detected

ID: go/goroutine-leak

Also available as: JSON · Markdown
85%Fix Rate
88%Confidence
50Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
121 active
1 active

Root Cause

Goroutines are not being cleaned up, usually from missing context cancellation or blocked channel operations.

generic

Workarounds

  1. 92% success Add select with context.Done() to every goroutine for cancellation
    go func(ctx context.Context) {
      for {
        select {
        case <-ctx.Done():
          return
        case msg := <-ch:
          process(msg)
        }
      }
    }(ctx)

    Sources: https://pkg.go.dev/context

  2. 90% success Use errgroup for managing goroutine lifecycles
    g, ctx := errgroup.WithContext(ctx)
    for _, item := range items {
      item := item
      g.Go(func() error {
        return process(ctx, item)
      })
    }
    if err := g.Wait(); err != nil {
      log.Fatal(err)
    }

    Sources: https://pkg.go.dev/golang.org/x/sync/errgroup

  3. 85% success Monitor goroutine count with runtime.NumGoroutine() in tests
    func TestNoLeak(t *testing.T) {
      before := runtime.NumGoroutine()
      doWork()
      time.Sleep(100 * time.Millisecond)
      after := runtime.NumGoroutine()
      if after > before+1 {
        t.Errorf("goroutine leak: before=%d after=%d", before, after)
      }
    }

    Sources: https://pkg.go.dev/runtime#NumGoroutine

Dead Ends

Common approaches that don't work:

  1. Increase GOMAXPROCS to handle more goroutines 80% fail

    GOMAXPROCS controls OS thread count, not goroutine count; leaked goroutines still consume memory

  2. Use runtime.Goexit() to kill goroutines 85% fail

    Goexit only terminates the calling goroutine; cannot kill other goroutines externally

Error Chain

Leads to:
Preceded by: