nats-io/nats-server · error
not enough nonce bytes read (%d != %d)
Error message
not enough nonce bytes read (%d != %d)
What it means
Thrown when rand.Read fails to fill the full AEAD nonce buffer (NonceSize bytes) used to encrypt the seed while generating block encryption keys. A short read from crypto/rand indicates a failed system entropy source, so the store aborts key generation rather than reusing/predictable nonces, which would be catastrophic for AES-GCM.
Source
Thrown at server/filestore.go:929
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, err
}
return aek, bek, seed, kek.Seal(nonce, nonce, seed, nil), nil
}
// Will generate the block encryption key.
func genBlockEncryptionKey(sc StoreCipher, seed, nonce []byte) (cipher.Stream, error) {
if sc == ChaCha {
return chacha20.NewUnauthenticatedCipher(seed, nonce)
} else if sc == AES {
block, err := aes.NewCipher(seed)
if err != nil {
return nil, errView on GitHub (pinned to 3a66a489d2)
Solutions
- Verify the host's entropy/random subsystem (getrandom, /dev/urandom) is functional and restore it
- Restart the node and retry the stream creation once entropy is replenished
- Run on an environment where crypto/rand is known-good (recent kernel, no blocked syscalls)
- Audit sandbox/seccomp rules that might limit getrandom(2)
Defensive patterns
Strategy: validation
Validate before calling
nonce := make([]byte, kek.NonceSize())
if n, err := crypto_rand.Read(nonce); err != nil || n != len(nonce) {
return fmt.Errorf("entropy source unhealthy: read %d/%d bytes (err=%v)", n, len(nonce), err)
} Try / catch
// Go: wrap stream creation and fail fast on crypto/rand anomalies
if err := createEncryptedStream(cfg); err != nil {
if strings.Contains(err.Error(), "not enough") {
// entropy fault: alert ops, do not retry blindly
}
return err
} Prevention
- Ensure the runtime environment exposes a working getrandom//dev/urandom
- Restart the process after entropy subsystem recovery
- Audit container security profiles for blocked randomness syscalls
- Pin server versions tested against your kernel
When it happens
Trigger: Creating an encrypted file-store stream (genBlockEncryptionKey path) when the kernel entropy source returns fewer bytes than requested without an error.
Common situations: Pentesting-style low-entropy VMs, misconfigured containers lacking /dev/urandom or getrandom(2), or heavy concurrent crypto operations on a degraded kernel.
Related errors
- not enough seed 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/6c077e88f11359fc.
Report an issue: GitHub.