-
Couldn't load subscription status.
- Fork 122
Description
Welcome
- Yes, I'm using the latest release.
- Yes, I've searched similar issues on GitHub and didn't find any.
What did you expect to see?
Expected all V1 UUIDs to be unique when generated concurrently, even with a fixed timestamp. The clock sequence mechanism should ensure uniqueness by incrementing when the timestamp doesn't advance.
According to RFC-9562, v1 UUIDs should be unique even when generated in rapid succession using clock sequence increments.
What did you see instead?
Massive UUID duplication in v1 generation under concurrent load with fixed timestamp:
- V1 UUIDs: 83,616 duplicates out of 100,000 total UUIDs (83.6% duplication rate!)
- V7 UUIDs: 100,000 unique UUIDs (0% duplication rate)
The duplicate v1 UUIDs only differ in the clock sequence bytes (positions 8-9), but many have identical values, indicating the clock sequence mechanism is failing to provide uniqueness.
Example duplicate UUIDs:
70d9b500-fa26-11dd-876f-322495cdf0f6
70d9b500-fa26-11dd-8770-322495cdf0f6
70d9b500-fa26-11dd-8771-322495cdf0f6
The problem appears to be specific to v1 UUID generation logic, not a general race condition, since v7 UUIDs work correctly using the same getClockSequence() function.
Reproduction steps
package main
import (
"sync"
"testing"
"time"
"github.com/gofrs/uuid/v5"
)
func TestV1DuplicationBug(t *testing.T) {
const numGoroutines = 100
const numUUIDs = 1000
// Test with fixed time to force clock sequence usage
fixedTime := time.Unix(1234567890, 0)
gen := uuid.NewGenWithOptions(
uuid.WithEpochFunc(func() time.Time {
return fixedTime // Always return same time to force clock sequence increment
}),
)
var wg sync.WaitGroup
uuidChan := make(chan uuid.UUID, numGoroutines*numUUIDs)
// Launch multiple goroutines generating V1 UUIDs simultaneously
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < numUUIDs; j++ {
u, err := gen.NewV1()
if err != nil {
t.Errorf("Failed to generate UUID: %v", err)
return
}
uuidChan <- u
}
}()
}
wg.Wait()
close(uuidChan)
// Check for duplicates
seen := make(map[uuid.UUID]bool)
duplicates := 0
for u := range uuidChan {
if seen[u] {
duplicates++
}
seen[u] = true
}
if duplicates > 0 {
t.Errorf("Found %d duplicate UUIDs out of %d total", duplicates, numGoroutines*numUUIDs)
}
}Version of flock
latest master branch (commit id: 78d4142)
Logs
<details>
$ go test -race -run TestRaceCondition -v
=== RUN TestRaceConditionUUIDGeneration
race_test.go:56: Found 83616 duplicate UUIDs out of 100000 total
race_test.go:59: Generated 16384 unique UUIDs across 100 goroutines
--- FAIL: TestRaceConditionUUIDGeneration (1.25s)
=== RUN TestRaceConditionV7UUIDGeneration
race_test.go:112: Generated 100000 unique V7 UUIDs across 100 goroutines
--- PASS: TestRaceConditionV7UUIDGeneration (0.16s)
FAIL
</details>Go environment
$ go version && go env
go version go1.24.4 darwin/arm64
GOARCH="arm64"
GOOS="darwin"
GOVERSION="go1.24.4"Validation
- Yes, I've included all information above (version, config, etc.).