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.
go
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.
Go
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.
Go
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.
Related guides
Go "test timed out after 10m0s" - Fix in CIFix Go "panic: test timed out after 10m0s" in CI - a test exceeded the default timeout, usually a hang or a s…
Go "fatal error: concurrent map writes" in test - Fix in CIFix Go "fatal error: concurrent map writes" during a test in CI - unsynchronized concurrent map access crashe…
Go "DATA RACE" detected during test (-race) - Fix in CIFix Go "WARNING: DATA RACE" under go test -race in CI - concurrent unsynchronized access to shared state. Add…