Go

Which runtime failures can't be recovered with recover?

Question 311HardGo 1.22 to 1.25

recover handles panics, both user panics and runtime-error panics (nil dereference, index out of range, nil map write, division by zero, failed type assertion, closing a closed channel). Some failures are fatal errors that bypass defer and recover and kill the process immediately:

  • fatal error: concurrent map writes / concurrent map read and map write
  • fatal error: all goroutines are asleep - deadlock!
  • Stack overflow (goroutine stack exceeds 1000000000-byte limit) from runaway recursion
  • Out of memory (runtime: out of memory)
  • Unlocking an unlocked sync.Mutex (fatal error: sync: unlock of unlocked mutex)
func main() {
	defer func() { fmt.Println("never printed:", recover()) }()
	m := map[int]int{}
	for i := range 100 {
		go func() { m[i] = i }() // usually: fatal error: concurrent map writes
	}
	time.Sleep(time.Second)
}

The runtime's map race check is best-effort (it still exists with the Swiss-table maps of Go 1.24), so a racy program may also just corrupt data silently. Likewise, os.Exit and log.Fatal skip deferred functions entirely. What the interviewer is checking: that you don't treat recover as a safety net for data races. Prevent those with sync.Mutex, sync.Map, or channels, and find them with go test -race.

More on Error Handling & panics

All 37 Error Handling & panics questions