netbirdio/netbird · error

could not generate %d random bytes: %v

Error message

could not generate %d random bytes: %v

What it means

io.ReadFull on crypto/rand.Reader failed while generating random bytes for the OAuth state (24 bytes) or PKCE code_verifier (64 bytes). crypto/rand.Reader is the OS CSPRNG; a failure or short read means the operating system's entropy source is unavailable or erroring, which is exceptional on a healthy system.

Source

Thrown at client/internal/auth/util.go:17

package auth

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"strings"
)

func randomBytesInHex(count int) (string, error) {
	buf := make([]byte, count)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		return "", fmt.Errorf("could not generate %d random bytes: %v", count, err)
	}

	return hex.EncodeToString(buf), nil
}

// validateTokenAudience checks that the token is a well-formed JWT whose
// audience claim matches the expected audience.
//
// It does NOT verify the token's cryptographic signature and therefore must not
// be treated as an authenticity check. The token is obtained by the client
// directly from the IdP token endpoint over TLS, and its signature is verified
// server-side by the management server against the IdP's JWKS
// (see shared/auth/jwt/validator.go). This function is only a client-side
// sanity check that the returned token targets the expected audience.
func validateTokenAudience(token string, audience string) error {
	if token == "" {
		return fmt.Errorf("token received is empty")
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Verify the OS entropy source is reachable inside the environment: check that getrandom(2)/ /dev/urandom works from the same container or sandbox.
  2. On VMs, attach a hardware or virtio RNG device, or seed entropy from the host.
  3. Retry the login once - the operation is cheap and transient failures are extremely rare.
  4. If running under a restrictive policy (seccomp, AppArmor, SELinux), allow the entropy syscall/device for the netbird process.
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm the OS CSPRNG is readable in this environment
func entropyAvailable() error {
    buf := make([]byte, 8)
    _, err := io.ReadFull(rand.Reader, buf)
    return err
}

Try / catch

state, err := randomBytesInHex(24)
if err != nil {
    // entropy source failure is almost always environmental; retry once,
    // then report 'OS entropy source unavailable' rather than raw error text
    state, err = randomBytesInHex(24)
    if err != nil {
        return AuthFlowInfo{}, fmt.Errorf("OS entropy source unavailable: %w", err)
    }
}

Prevention

When it happens

Trigger: rand.Reader.Read returns an error or fewer bytes than requested: getrandom(2) or /dev/urandom unavailable in a restricted sandbox or container, early-boot entropy starvation on embedded systems, a VM with a broken or missing hardware RNG passthrough, or file-descriptor exhaustion preventing the entropy device open on older implementations.

Common situations: Minimal Docker, gVisor, or custom-seccomp sandstones blocking entropy syscalls; custom-compiled kernels without the random device; userspace starting before the kernel CRNG is initialized; embedded or VM environments without virtio-rng.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/2aef28ba087b201d. Report an issue: GitHub.