nats-io/nats-server · error
not enough seed bytes read (%d != %d
Error message
not enough seed bytes read (%d != %d
What it means
This error is thrown when crypto/rand.Read fills the 32-byte seed buffer with fewer bytes than requested while generating the encryption keys for a file store stream. In Go, crypto/rand.Read is documented to always succeed or return an error, so a short read signals a broken/failed entropy source. The store treats it as unrecoverable and aborts key generation.
Source
Thrown at server/filestore.go:916
rb, err := fs.prf([]byte(context))
if err != nil {
return nil, nil, nil, nil, err
}
sc := fs.fcfg.Cipher
kek, err := genEncryptionKey(sc, rb)
if err != nil {
return nil, nil, nil, nil, err
}
// Generate random asset encryption key seed.
const seedSize = 32
seed = make([]byte, seedSize)
if n, err := rand.Read(seed); err != nil {
return nil, nil, nil, nil, err
} else if n != seedSize {
return nil, nil, nil, nil, fmt.Errorf("not enough seed bytes read (%d != %d", n, seedSize)
}
aek, err = genEncryptionKey(sc, seed)
if err != nil {
return nil, nil, nil, nil, err
}
// Generate our nonce. Use same buffer to hold encrypted seed.
nonce := make([]byte, kek.NonceSize(), kek.NonceSize()+len(seed)+kek.Overhead())
if n, err := rand.Read(nonce); err != nil {
return nil, nil, nil, nil, err
} else if n != len(nonce) {
return nil, nil, nil, nil, fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce))
}
bek, err = genBlockEncryptionKey(sc, seed[:], nonce)
if err != nil {
return nil, nil, nil, nil, errView on GitHub (pinned to 3a66a489d2)
Solutions
- Check host entropy health (e.g. /proc/sys/kernel/random/entropy_avail, getrandom availability) and fix the OS/environment issue
- Retry the operation once entropy is available; crypto/rand short reads are almost always transient environment faults
- Upgrade Go/runtime and OS kernel so crypto/rand.Read behavior matches modern guarantees
- Remove any wrappers or LD_PRELOAD interposers that interfere with system randomness
Example fix
// before
if n, err := rand.Read(seed); err != nil {
return nil, err
} else if n != seedSize {
return nil, fmt.Errorf("not enough seed bytes read (%d != %d", n, seedSize)
}
// after
// fix the environment first; no code change fixes a failing entropy source.
// At minimum, close the missing paren when logging:
return nil, fmt.Errorf("not enough seed bytes read (%d != %d)", n, seedSize) Defensive patterns
Strategy: validation
Validate before calling
if n, err := crypto_rand.Read(seed); err != nil || n != len(seed) {
return fmt.Errorf("entropy source unhealthy: read %d/%d bytes (err=%v)", n, len(seed), err)
} Try / catch
// Go: check both error and short read
n, err := rand.Read(seed)
if err != nil {
return fmt.Errorf("rand.Read failed: %w", err)
}
if n != len(seed) {
return fmt.Errorf("short entropy read: %d != %d", n, len(seed))
} Prevention
- Monitor host entropy health (getrandom availability, entropy_avail)
- Keep kernels and Go runtime up to date
- Avoid sandboxes/seccomp profiles that block system randomness syscalls
- Alert on any crypto/rand error in server logs
When it happens
Trigger: Calling stream/filestore setup (e.g. creating an encrypted file store via AddStream with a crypto-principalled account) when the OS entropy source fails mid-Read, returning n < 32 without an error.
Common situations: Container/kernel environments with exhausted or blocked getrandom(2), unusual sandboxed VMs, or custom rand.Source replacement hacks on Linux hosts with depleted entropy.
Related errors
- not enough nonce bytes read (%d != %d)
- not enough overwrite bytes read (%d != %d)
- ErrBadCryptoStoreProvider
- unknown compression algorithm
- name required
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/77c9d9fb596f0f3d.
Report an issue: GitHub.