Panic when uuid.New().String()
nfoerster opened this issue · 1 comments
I run a horizontally scaled application in k8s producing UUIDs for messages. However, rarely, some replicated pods restart due to a panic coming for the UUID library.
panic: unexpected EOF
goroutine 197286 [running]:
github.com/google/uuid.Must(...)
/home/vagrant/go/pkg/mod/github.com/google/uuid@v1.3.0/uuid.go:178
github.com/google/uuid.New(...)
/home/vagrant/go/pkg/mod/github.com/google/uuid@v1.3.0/version4.go:14
Is there any OS/library causing these issues, like too little entropy? On my local machine, I run a test producing billions of UUIDs without any panic.
Well, I can only guess why that happens. Too little entropy might be the problem, AFAIK crypto/rand
(used by uuid.UUID
) uses syscalls and should typically not create duplicates. The comments state:
// NewRandom returns a Random (Version 4) UUID.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// Uses the randomness pool if it was enabled with EnableRandPool.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 10−11),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
Internally, the error happens as the io.Reader
tries to read from either the rand pool of uuid
or from the std rand.Reader
. Since you haven't mentioned uuid.EnableRandPool
I'm assuming you're not using it, meaning for UUID creation, uuid
reads from this rand.Reader
. Under the hood, at least for Linux and Unix-ish operating systems, it uses the getrandom
, or getentropy
syscalls or reads from /dev/urandom
.
Too little entropy might lead to a sys-level error, e.g. for getrandom see EAGAIN.
However, I have two suggestions for you to try out:
uuid.EnableRandPool
, maybe it helps, comments state:
// EnableRandPool enables internal randomness pool used for Random
// (Version 4) UUID generation. The pool contains random bytes read from
// the random number generator on demand in batches. Enabling the pool
// may improve the UUID generation throughput significantly.
//
// Since the pool is stored on the Go heap, this feature may be a bad fit
// for security sensitive applications.
- Otherwise, is it an option to not use
uuid.New
oruuid.NewString
but insteaduuid.NewRandom
and re-try upon error? Becauseuuid.New
is equivalent touuid.Must(uuid.NewRandom)
.