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
- Ensure /dev/urandom is available and readable inside the container/sandbox.
- Loosen seccomp/AppArmor profiles to permit the getrandom syscall and /dev/urandom access.
- Delay startup until the kernel CSPRNG is seeded on embedded/early-boot environments.
- 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
- Expose /dev/urandom and permit the getrandom syscall in containers/seccomp.
- Probe crypto/rand at startup to fail fast in broken environments.
- Set an explicit multipart boundary to bypass unsafeRandString when randomness is unavailable.
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
- boundary generation: %w
- set boundary error: %w
- failed to close multipart writer: %w
- write formdata error: %w
- create file error: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/9125460c050782f8.json.
Report an issue: GitHub.