gofiber/fiber · critical

rand.Read failed: %w

Error message

rand.Read failed: %w

What it means

Returned by unsafeRandString (client/hooks.go:53) when the initial crypto/rand.Read of n bytes fails. unsafeRandString generates random multipart-boundary strings; the first bulk read produces all n bytes at once. A failure here means the kernel could not supply cryptographic randomness, which is exceedingly rare on a healthy Linux/macOS host.

Source

Thrown at client/hooks.go:53

	letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
)

// unsafeRandString returns a random string of length n.
// An error is returned if the random source fails.
func unsafeRandString(n int) (string, error) {
	inputLength := byte(len(letterBytes))

	// Compute the largest multiple of inputLength ≤ 256 to avoid modulo bias.
	// Any byte ≥ max will be rejected and re‑read.
	maxLength := byte(256 - (256 % int(inputLength))) //nolint:gosec // G115: integer overflow conversion int -> byte

	out := make([]byte, n)
	buf := make([]byte, n)

	// Read n raw bytes in one shot
	if _, err := rand.Read(buf); err != nil {
		return "", fmt.Errorf("rand.Read failed: %w", err)
	}

	for i, b := range buf {
		// Reject values ≥ maxLength
		for b >= maxLength {
			if _, err := rand.Read(buf[i : i+1]); err != nil {
				return "", fmt.Errorf("rand.Read failed: %w", err)
			}
			b = buf[i]
		}
		out[i] = letterBytes[b%inputLength]
	}

	return utils.UnsafeString(out), nil
}

// parserRequestURL sets options for the hostclient and normalizes the URL.
// It merges the baseURL with the request URI if needed and applies query and path parameters.

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Ensure /dev/urandom is available and readable inside the container/sandbox.
  2. Loosen seccomp/AppArmor profiles to permit the getrandom syscall and /dev/urandom access.
  3. Delay startup until the kernel CSPRNG is seeded on embedded/early-boot environments.
  4. Handle the error from the request that triggers file uploads (it propagates up from parserRequestHeader).

Example fix

// before — upload attempted in an environment without /dev/urandom
resp, err := client.R().SetFiles("./upload.txt").Get(url)

// after — guard the upload path and report the environment problem
resp, err := client.R().SetFiles("./upload.txt").Get(url)
if err != nil && strings.Contains(err.Error(), "rand.Read failed") {
    return fmt.Errorf("CSPRNG unavailable for boundary generation; check /dev/urandom: %w", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Probe the CSPRNG at startup so failures surface early.
func probeCSPRNG() error {
    b := make([]byte, 16)
    _, err := rand.Read(b)
    return err
}

Try / catch

if _, err := rand.Read(make([]byte, 16)); err != nil {
    // CSPRNG unavailable — uploads that need a boundary will fail;
    // fall back to a preconfigured boundary.
    req.SetBoundary("FixedFallbackBoundary")
}

Prevention

When it happens

Trigger: crypto/rand.Read returns an error — typically on a system with a broken /dev/urandom, an extremely early boot before the CSPRNG is seeded, a chroot/container without /dev/urandom, or an OS-level entropy failure. Triggered during multipart file uploads when the client auto-generates a boundary.

Common situations: Running inside a minimal container/seccomp profile that blocks /dev/urandom reads; booting code before the kernel RNG is ready (embedded devices); a misconfigured sandbox; syscall interception (some tracing/latency tools) that breaks getrandom(2).

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/9125460c050782f8.json. Report an issue: GitHub.