Go "fatal error: concurrent map writes" in Tests - Fix in CI
Go maps are not safe for concurrent use. When two goroutines write the same map (or one writes while another reads) without synchronization, the runtime detects it and aborts the whole process with a fatal error.
What this error means
A test run crashes hard with fatal error: concurrent map writes (or concurrent map read and map write) and a goroutine dump - not a normal --- FAIL. It can be intermittent, surfacing only when goroutines happen to collide.
fatal error: concurrent map writes
goroutine 34 [running]:
main.(*Cache).Set(...)
/app/cache.go:21 +0x1f4Common causes
A shared map written from multiple goroutines
A cache, registry, or result map is mutated concurrently without a lock. The runtime’s built-in check aborts the process on the unsafe access.
Tests exposing a real production data race
Parallel tests (t.Parallel()) or concurrent helpers exercise a map that production code never protected, surfacing a genuine race.
How to fix it
Guard the map with a mutex
Serialize access with a sync.Mutex/RWMutex around every read and write.
type Cache struct {
mu sync.RWMutex
m map[string]string
}
func (c *Cache) Set(k, v string) {
c.mu.Lock(); defer c.mu.Unlock()
c.m[k] = v
}Use sync.Map for concurrent access
For read-heavy concurrent maps, sync.Map avoids manual locking.
var m sync.Map
m.Store(key, value)
v, ok := m.Load(key)Catch it with the race detector
Run with -race to get the exact conflicting accesses, then add synchronization.
go test -race ./...How to prevent it
- Protect shared maps with a mutex or use
sync.Map. - Run
go test -racein CI to catch unsynchronized access early. - Treat any fatal map error as a real production bug, not a flake.