ory/hydra · critical

cannot generate nonce

Error message

cannot generate nonce

What it means

After creating the AEAD, PageToken.encrypt generates a random nonce with crypto/rand.Read to prepend to the ciphertext. rand.Read on crypto/rand essentially never fails except when the OS entropy source is unavailable/broken, so this error signals a system-level RNG failure.

Source

Thrown at oryx/pagination/keysetpagination_v2/page_token.go:192

func NewPageToken(cols ...Column) PageToken { return PageToken{cols: cols} }

func (t *PageToken) encrypt(key [32]byte) (string, error) {
	raw, err := json.Marshal(t)
	if err != nil {
		return "", errors.Wrap(err, "cannot marshal page token")
	}

	a, err := aead.New(key)
	if err != nil {
		return "", errors.Wrap(err, "cannot create AEAD")
	}

	// The nonce is prepended to the ciphertext. AEADs that manage the nonce
	// internally report a nonce size of zero, so this also covers them.
	nonce := make([]byte, a.NonceSize())
	if _, err := rand.Read(nonce); err != nil {
		return "", errors.Wrap(err, "cannot generate nonce")
	}

	return base64.URLEncoding.EncodeToString(a.Seal(nonce, nonce, raw, []byte(pageTokenContext))), nil
}

func (t *PageToken) decrypt(key [32]byte, s string) error {
	if s == "" {
		return errors.WithStack(ErrInvalidPaginationToken())
	}

	raw, err := base64.URLEncoding.DecodeString(s)
	if err != nil {
		return errors.WithStack(ErrInvalidPaginationToken())
	}

	dec, err := openAEAD(key, raw)
	if err != nil {
		// Tokens issued before the switch to a context-bound AEAD are sealed

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Verify /dev/urandom exists and is readable inside the container: ls -l /dev/urandom
  2. Check seccomp/apparmor policies are not blocking getrandom(2) syscall
  3. Update the base image/kernel so getrandom is available
  4. Retry the deployment on a known-good host to confirm it is environment-specific
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure the entropy source is readable at startup
if _, err := os.Stat("/dev/urandom"); err != nil {
    log.Fatal("crypto entropy source unavailable: /dev/urandom missing")
}
if _, err := rand.Read(make([]byte, 16)); err != nil {
    log.Fatal("crypto/rand unavailable at startup")
}

Try / catch

enc, err := Encrypt(key, token)
if err != nil && strings.Contains(err.Error(), "cannot generate nonce") {
    // environment-level RNG failure: retry once, then surface as 500
    return nil, status.Error(codes.Internal, "system RNG unavailable")
}

Prevention

When it happens

Trigger: crypto/rand.Read returns an error during Encrypt — typically on systems where /dev/urandom is inaccessible, in heavily restricted containers/chroots, or with a broken Go runtime entropy setup.

Common situations: Running in a container with no access to the kernel RNG device, seccomp policies blocking getrandom(2), or exotic sandboxes (some CI environments, old kernels without getrandom and blocked /dev/urandom).

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/98ca27a5ac2ed202. Report an issue: GitHub.