OpenNHP/opennhp · warning

failed to generate UUID:

Error message

failed to generate UUID: 

What it means

NewUUID builds a v4 UUID from a math/rand source seeded with the current time; if reading 16 random bytes from that source fails (essentially never for math/rand, but possible in principle), the raw error is wrapped into this message and returned.

Solutions

  1. Retry the call; a transient rand failure is practically impossible and safe to retry
  2. If this occurs in tests, fix the injected failing rand source
  3. Consider crypto/rand-based UUID generation if the UUID must be unguessable (which would eliminate this path's realism concerns differently)
  4. Inspect the wrapped err text after the colon for the actual root cause

Example fix

// before
id, err := NewUUID()
if err != nil {
    return err
}
// after
id, err := NewUUID()
if err != nil {
    log.Warnf("uuid generation failed, retrying: %v", err)
    id, err = NewUUID()
    if err != nil { return err }
}
Defensive patterns

Strategy: try-catch

Try / catch

id, err := NewUUID()
if err != nil {
    // wrapped message includes root cause after 'failed to generate UUID: '
    return fmt.Errorf("NewUUID: %w", err)
}

Prevention

When it happens

Trigger: rng.Read on the freshly seeded *rand.Rand returns a non-nil error — practically only when the error is induced in tests or the rand source is replaced by a failing implementation.

Common situations: Seen in TestUUID when injecting a failing reader; not expected in production with the default time-seeded math/rand source.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/aedf8a9fb0352487. Report an issue: GitHub.

Appendix: source

Thrown at nhp/utils/uuid.go:21

import (
	"errors"
	"fmt"
	"math/rand"
	"time"

	"github.com/google/uuid"
)

// NewUUID generates a UUID using math/rand. For cryptographically secure UUIDs,
// use GenerateUUIDv4() instead which uses crypto/rand.
//
//nolint:gosec // G404: math/rand is acceptable for non-security UUID generation
func NewUUID() (string, error) {
	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
	uuid := make([]byte, 16)
	_, err := rng.Read(uuid)
	if err != nil {
		return "", errors.New("failed to generate UUID: " + err.Error())
	}

	// Set version bits (version 4)
	uuid[6] = (uuid[6] & 0x0F) | 0x40
	// Set variant bits (variant 1)
	uuid[8] = (uuid[8] & 0x3F) | 0x80

	return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
}

// RandNumber returns a random 4-digit number (1000-10999) for non-security purposes.
//
//nolint:gosec // G404: math/rand is acceptable for non-security random numbers
func RandNumber() int {
	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
	randomNumber := rng.Intn(10000)
	if randomNumber < 1000 {
		randomNumber += 1000

View on GitHub (pinned to 6e04ca5ff0)