concurrent map writes
Go Programming Language
Severity: CriticalWhat Does This Error Mean?
Go maps are not safe for concurrent use from multiple goroutines. Two goroutines writing to the same map at the same time causes a fatal crash. This is not a panic — it cannot be recovered. The program exits immediately.
Affected Models
- Go 1.21
- Go 1.22
- Go 1.23
- Go 1.24
Common Causes
- Two or more goroutines writing to the same map simultaneously
- One goroutine reading and another writing to the same map at the same time
- Sharing a map through a closure between goroutines without synchronization
- Using a map as a shared cache without a mutex or lock
- Not realizing a library function runs its callback in a goroutine
How to Fix It
-
Add a sync.RWMutex to protect your map. Lock before writing, unlock after.
var mu sync.RWMutex — use mu.Lock() / mu.Unlock() for writes, mu.RLock() / mu.RUnlock() for reads.
-
Switch to sync.Map, which is built for concurrent access.
var m sync.Map — use m.Store(key, value) and m.Load(key). No mutex needed.
-
Use the race detector during development: go run -race main.go
This catches data races before they crash production. Make it part of your test workflow.
-
Isolate map ownership — let only one goroutine own and write to the map.
Pass updates through a channel to a single 'manager' goroutine. This is the cleanest Go-idiomatic solution.
-
Add go test -race to your CI pipeline to catch race conditions automatically.
Race conditions are non-deterministic. Tests pass most of the time but fail randomly in production.
When to Call a Professional
If this error appears in a production service, stop and audit all shared state. Data races can cause silent corruption — not just crashes. Consider a code review focused on concurrency safety.
Frequently Asked Questions
Why can't I recover() from a concurrent map write?
Go's runtime deliberately makes this a fatal error, not a panic. The design choice is intentional — a corrupted map is unrecoverable. recover() only works for panics, not fatal errors.
Is sync.Map always better than a map with a mutex?
Not always. sync.Map is optimized for read-heavy workloads with infrequent writes. For write-heavy workloads, a map with sync.RWMutex is often faster. Benchmark both for your specific use case.
Does this error appear if two goroutines only read from the map?
No. Concurrent reads from a map are safe in Go. The crash only happens when at least one goroutine is writing. Write and read at the same time is also unsafe.