Go "all goroutines are asleep - deadlock" in test - Fix in CI
When every goroutine is blocked with no way to proceed, the Go runtime detects the deadlock and aborts. In a test this usually means an unmatched channel send/receive or a held lock.
What this error means
A run crashes with fatal error: all goroutines are asleep - deadlock! and a goroutine dump. It often shows in CI where ordering differs enough to leave a channel operation unmatched.
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
example.com/app.TestPipeline(...)
/app/pipe_test.go:19 +0x90Common causes
Unmatched channel operation
A receive waits for a send that never happens (or vice versa), so the test blocks forever.
Lock never released
A mutex is locked and not unlocked on some path, blocking every goroutine that needs it.
How to fix it
Match every channel operation
- Ensure every send has a receiver and every receive a sender; close channels when done.
close(ch) // signal no more sends
for v := range ch { /* ... */ }Add a timeout to surface the block
- Use select with a timeout so a deadlock fails fast with a clear message instead of hanging.
select {
case v := <-ch:
_ = v
case <-time.After(time.Second):
t.Fatal("timed out waiting on ch")
}How to prevent it
- Always pair channel sends and receives; close when done.
- Defer mutex unlocks so they always run.
- Use select-with-timeout in tests to avoid silent hangs.