ory/hydra · critical
panic during JSON Web Key generation for set %q: %v
Error message
panic during JSON Web Key generation for set %q: %v
What it means
This error converts a panic raised inside the singleflight-generated JWK creation into a normal error. Without the recover, a panic in singleflight.Do would crash the entire process, including concurrent requests waiting on the same flight. The message reports the JWK set name and the recovered panic value.
Source
Thrown at jwk/helper.go:90
// The network ID scopes the flight to one tenant. The NUL separators keep
// distinct (set, kid) tuples from mapping to the same key; results are
// shared between all callers on the same key, so the key must never be
// ambiguous.
key := r.Networker().NetworkID(ctx).String() + "\x00" + set + "\x00" + kid
// A flight is bounded by generateTimeout, so waiting much longer than that
// means it died without delivering (e.g. runtime.Goexit in a test); error
// out rather than blocking forever.
ctx, cancel := context.WithTimeout(ctx, 2*generateTimeout)
defer cancel()
ch := generateFlight.DoChan(key, func() (_ any, err error) {
// A panic must surface as an error: singleflight would otherwise
// crash the whole process when channel waiters are present.
defer func() {
if e := recover(); e != nil {
err = errors.Errorf("panic during JSON Web Key generation for set %q: %v", set, e)
}
}()
// The flight must not be canceled by the request that happened to
// start it: other requests may be waiting on the result. Context
// values (network ID, tracing) are preserved.
fctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), generateTimeout)
defer cancel()
return readOrGenerateKeySet(fctx, r, set, kid, alg, use)
})
select {
case <-ctx.Done():
return nil, errors.WithStack(ctx.Err())
case result := <-ch:
if result.Err != nil {
return nil, result.ErrView on GitHub (pinned to 4174065ffb)
Solutions
- Inspect the %v payload in the log to identify the panicking code path inside the JWK generation flight
- Fix the root cause in the key-generation code (check crypto/rand availability, memory limits for RSA 4096, uuid generation)
- Retry the request — the error is transient from the caller's perspective and the flight result is not cached on panic
- Reduce concurrency pressure on the same JWK set while investigating
Defensive patterns
Strategy: try-catch
Try / catch
keys, err := mgr.GetOrGenerateKeySet(ctx, set)
if err != nil {
if strings.Contains(err.Error(), "panic during JSON Web Key generation") {
log.WithError(err).Error("jwk generation panicked; retrying")
return retryWithBackoff(ctx, func() error { _, err := mgr.GetOrGenerateKeySet(ctx, set); return err })
}
return err
} Prevention
- Log the recovered panic value to find and fix the root cause in key generation
- Keep RSA bit size within memory budgets (4096-bit keys are expensive under load)
- Monitor for repeated panics on the same JWK set — indicates a deterministic bug, not transient
- Ensure crypto/rand and uuid generation are healthy in the deployment environment
When it happens
Trigger: Any panic thrown inside the flight function that generates keys for a JWK set — e.g. nil dereference in key generation, uuid.Must failing, crypto randomness unavailable, or a bug in josex.NewSigningKey — while other requests may be waiting on the same singleflight channel.
Common situations: Hardware/OS-level entropy failures (crypto/rand read error panics or uuid.Must panics); concurrent first-time key generation for the same set triggering a latent bug; memory exhaustion during 4096-bit RSA key generation under load.
Related errors
- invalid JWK key
- priv/pub JWK key mismatch
- unknown algorithm %s for signing key
- unknown algorithm %s for encryption key
- square/go-jose: parse error, got '%s', '%s' and '%s'
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/d623ce0842fec3b3.
Report an issue: GitHub.