Goroutine spawned without context or stop channel
What this failure means
A goroutine is spawned with an infinite loop and no context cancellation, stop channel, or WaitGroup — it will leak when the calling function returns.
Diagnosis
A goroutine is started with go func() and runs an infinite or long-running
loop without any mechanism to stop it. When the parent context or server shuts
down, this goroutine keeps running, leaking memory and CPU over time.
Common patterns:
- A background poller that loops with
time.Sleepand no shutdown signal - A cache-refresh goroutine that runs forever without a done channel
- A background worker spawned in
init()ormain()without lifecycle control
Fix steps
-
Accept a
context.Contextparameter and checkctx.Done()in the loop:func StartWorker(ctx context.Context) { go func() { for { select { case <-ctx.Done(): return default: doWork() time.Sleep(time.Second) } } }() } -
Alternatively, use a stop channel:
stop <- struct{}{}from the caller andcase <-stop: returnin the goroutine select. -
Track goroutines with a
sync.WaitGroupso callers can wait for clean shutdown. -
For periodic background work, prefer
time.NewTickerwith a select overtime.Sleepin a loop — the ticker can be stopped.
Validation
- Run
faultline inspect .from the repository root and confirm this source finding is absent or intentionally mitigated. - Run
go test -race ./...to catch races introduced during cleanup. - Confirm that the background goroutine exits cleanly when the context is cancelled.
Why it matters
Goroutine leaks accumulate silently. Each leaked goroutine holds its stack and any variables it closes over. In long-running services, hundreds of leaked goroutines can exhaust memory, hold open database connections, or prevent clean shutdown of a Kubernetes pod, causing the process to be force-killed instead of draining gracefully.
Try it locally
make test
rg -n 'go func' .
go test -race ./...
go vet ./...
How Faultline detects it
Use faultline explain goroutine-leak to see the full playbook.
faultline analyze build.log
faultline explain goroutine-leak
Generated from playbooks/bundled/source/goroutine-leak.yaml. Do not edit directly.