fatal error: concurrent map writes, explained

Read the explanation
What if

Two goroutines write one plain map at the same time. The Go runtime notices and stops the whole program.

Predict first

Two goroutines do counts[k]++ on the same plain map, a million times each. What happens?

012345go ×2wg.Wait()main: println: never runsnevercounts[i%10]++g2: counts[i%10]++writeg2: fatal error: concurrent map writesfatal

Tap any block to see what that thread is doing.

  • Running
  • Waiting / parked
  • Skipped
  • Error
Step 1/5

main starts two goroutines that both count into one plain map.

1func main() {2    counts := map[int]int{}3    var wg sync.WaitGroup4    for range 2 {5        wg.Add(1)6        go func() {7            defer wg.Done()8            for i := range 1_000_000 {9                counts[i%10]++ // both goroutines write the map at once10            }11        }()12    }13    wg.Wait()14    fmt.Println(len(counts), "keys")15}

Explanation

What just happened

Both goroutines did counts[i%10]++ on one plain map. A Go map isn’t built for two writers at once, and the runtime checks for exactly that. When g2 wrote while g1 was writing, it stopped the program: fatal error: concurrent map writes, exit code 2. Nothing after that ran.

Try the what-if switch

Why crash on purpose?

A map written by two goroutines can end up internally broken, and that could show up much later as wrong data. Stopping right away, at the line that did it, is easier to debug.

Watch out

The check is best effort: a run where the two writes happen not to overlap passes. Don’t trust a green test; guard every access, reads included.

Common questions

What does fatal error: concurrent map writes mean?

Two goroutines wrote the same map at the same time. Go maps have no lock inside, so the runtime stops the whole program with exit code 2 rather than risk a corrupted map.

Can I recover from concurrent map writes?

No. It's a fatal error, not a panic: recover() doesn't catch it, and the process dies. Fix the code instead: guard the map with a sync.Mutex.

Do map reads need a lock too?

Yes, if another goroutine may be writing. A read without the lock during a write crashes the same way: fatal error: concurrent map read and map write.

Verified: this timeline matches a real program, checked in CI on Go 1.26 and 1.27. How we verify. Unclear or wrong? Tell us