Go race detector found a data race

The Go race detector identified a data race: two goroutines accessed the same memory location concurrently, with at least one performing a write, without any synchronization between them.

go-data-race high confidence test go

Matched signals

  • WARNING: DATA RACE
  • DATA RACE
  • Previous read at
  • Previous write at
  • Read at 0x
  • Write at 0x
  • Goroutine.*running
  • PASS (race)

Go race detector found a data race

What this failure means

The Go race detector identified a data race: two goroutines accessed the same memory location concurrently, with at least one performing a write, without any synchronization between them.

Symptoms

Faultline looks for one or more of these log fragments:

WARNING: DATA RACE
DATA RACE
Previous read at
Previous write at
Read at 0x
Write at 0x
Goroutine.*running
PASS (race)

Diagnosis

The Go race detector identified a data race: two goroutines accessed the same memory location concurrently, with at least one performing a write, without any synchronization between them.

Fix steps

  1. Read the full race report — it shows both goroutine stacks and the file/line for each conflicting access.
  2. Protect the shared variable with sync.Mutex or sync.RWMutex, or use an atomic operation (sync/atomic) for simple counters.
  3. Replace concurrent map access with sync.Map or add a sync.RWMutex around reads and writes.
  4. For loop-variable captures: copy the variable into a local before launching the goroutine: v := v.
  5. Run locally to reproduce: go test -race ./... or go test -race -count=5 ./... for intermittent races.

Validation

  • Re-run the local reproduction command after the fix.
  • go test -race ./…
  • go test -race -count=10 ./path/to/package

Why it matters

Go’s race detector instruments every memory access at compile time (go test -race or go build -race). When it detects unsynchronized concurrent access, it prints the goroutine stacks for both the current and the previous conflicting access and exits with a non-zero status. Common causes: shared variable modified in a goroutine without a mutex, map written from multiple goroutines, or a closure capturing a loop variable that races with goroutines launched inside the loop.

Prevention

  • Add go test -race ./... as a required CI check on every PR.
  • Use go vet and staticcheck alongside the race detector to catch common sharing patterns before tests are written.
  • Prefer channel-based state sharing over shared memory for new concurrency code to reduce the likelihood of races by design.

Try it locally

go test -race ./...
go test -race -count=10 ./path/to/package

How Faultline detects it

Use faultline explain go-data-race to see the full playbook.

faultline analyze build.log
faultline explain go-data-race

Generated from playbooks/bundled/log/test/go-data-race.yaml. Do not edit directly.

Try it on your own failed log

$ faultline analyze failed.log
Want this across every CI run? Faultline Teams tracks recurring failures across all your repos and surfaces patterns in a shared dashboard.