{"record":{"id":"98ca27a5ac2ed202","repo":"ory/hydra","slug":"cannot-generate-nonce","errorCode":null,"errorMessage":"cannot generate nonce","messagePattern":"cannot generate nonce","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"oryx/pagination/keysetpagination_v2/page_token.go","lineNumber":192,"sourceCode":"\nfunc NewPageToken(cols ...Column) PageToken { return PageToken{cols: cols} }\n\nfunc (t *PageToken) encrypt(key [32]byte) (string, error) {\n\traw, err := json.Marshal(t)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"cannot marshal page token\")\n\t}\n\n\ta, err := aead.New(key)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"cannot create AEAD\")\n\t}\n\n\t// The nonce is prepended to the ciphertext. AEADs that manage the nonce\n\t// internally report a nonce size of zero, so this also covers them.\n\tnonce := make([]byte, a.NonceSize())\n\tif _, err := rand.Read(nonce); err != nil {\n\t\treturn \"\", errors.Wrap(err, \"cannot generate nonce\")\n\t}\n\n\treturn base64.URLEncoding.EncodeToString(a.Seal(nonce, nonce, raw, []byte(pageTokenContext))), nil\n}\n\nfunc (t *PageToken) decrypt(key [32]byte, s string) error {\n\tif s == \"\" {\n\t\treturn errors.WithStack(ErrInvalidPaginationToken())\n\t}\n\n\traw, err := base64.URLEncoding.DecodeString(s)\n\tif err != nil {\n\t\treturn errors.WithStack(ErrInvalidPaginationToken())\n\t}\n\n\tdec, err := openAEAD(key, raw)\n\tif err != nil {\n\t\t// Tokens issued before the switch to a context-bound AEAD are sealed","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/pagination/keysetpagination_v2/page_token.go#L174-L210","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Verify /dev/urandom exists and is readable inside the container: ls -l /dev/urandom","Check seccomp/apparmor policies are not blocking getrandom(2) syscall","Update the base image/kernel so getrandom is available","Retry the deployment on a known-good host to confirm it is environment-specific"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-flight: ensure the entropy source is readable at startup\nif _, err := os.Stat(\"/dev/urandom\"); err != nil {\n    log.Fatal(\"crypto entropy source unavailable: /dev/urandom missing\")\n}\nif _, err := rand.Read(make([]byte, 16)); err != nil {\n    log.Fatal(\"crypto/rand unavailable at startup\")\n}","typeGuard":null,"tryCatchPattern":"enc, err := Encrypt(key, token)\nif err != nil && strings.Contains(err.Error(), \"cannot generate nonce\") {\n    // environment-level RNG failure: retry once, then surface as 500\n    return nil, status.Error(codes.Internal, \"system RNG unavailable\")\n}","preventionTips":["Verify /dev/urandom is present in container images (no distroless stripping of it)","Audit seccomp/apparmor profiles for getrandom(2) blocks","Do a crypto/rand smoke check during application startup","Run crypto/rand reads on the main runtime, not inside chrooted/sandboxed helpers"],"tags":["crypto","random","entropy"],"backgroundTag":"entropy-source-unavailable","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}