ory/hydra · error
key not found
Error message
key not found
What it means
jwk.FindPublicKey filters a JOSE key set down to its public keys via ExcludePrivateKeys and errors when nothing remains. It means the provided JSONWebKeySet contains no public key to use — typically for verifying a signature. The library throws it rather than silently returning a nil key.
Source
Thrown at jwk/helper.go:146
r.Logger().Warnf("JSON Web Key Set %q does not exist yet, generating new key pair...", set)
default:
return nil, err
}
return r.KeyManager().GenerateAndPersistKeySet(ctx, set, kid, alg, use)
}
func First(keys []jose.JSONWebKey) *jose.JSONWebKey {
if len(keys) == 0 {
return nil
}
return &keys[0]
}
func FindPublicKey(set *jose.JSONWebKeySet) (key *jose.JSONWebKey, err error) {
keys := ExcludePrivateKeys(set)
if len(keys.Keys) == 0 {
return nil, errors.New("key not found")
}
return First(keys.Keys), nil
}
func FindPrivateKey(set *jose.JSONWebKeySet) (key *jose.JSONWebKey, err error) {
keys := ExcludePublicKeys(set)
if len(keys.Keys) == 0 {
return nil, errors.New("key not found")
}
return First(keys.Keys), nil
}
func ExcludePublicKeys(set *jose.JSONWebKeySet) *jose.JSONWebKeySet {
keys := new(jose.JSONWebKeySet)
for _, k := range set.Keys {
if !k.IsPublic() {View on GitHub (pinned to 4174065ffb)
Solutions
- Verify the JWKS source actually returns at least one public key (`curl` the jwks_uri and inspect `keys`).
- Regenerate/republish the key set including the public component of the signing key.
- Check key filtering logic upstream — ensure the set passed in is not pre-stripped of public keys.
- Refresh the cached key set after rotation so the new public key is present.
Example fix
// before
key, err := jwk.FindPublicKey(&jose.JSONWebKeySet{})
// after: ensure the set has public keys first
set := fetchJWKS(ctx, jwksURI)
if len(jwk.ExcludePrivateKeys(set).Keys) == 0 {
return fmt.Errorf("no public keys at %s", jwksURI)
}
key, err := jwk.FindPublicKey(set) Defensive patterns
Strategy: type-guard
Validate before calling
// check the set has public keys before calling FindPublicKey
if len(jwk.ExcludePrivateKeys(set).Keys) == 0 {
return nil, fmt.Errorf("JWKS from %s has no public keys", uri)
} Type guard
func hasPublicKeys(set *jose.JSONWebKeySet) bool {
return set != nil && len(jwk.ExcludePrivateKeys(set).Keys) > 0
} Try / catch
// treat as a fetch/cache problem and refresh
key, err := jwk.FindPublicKey(set)
if err != nil && err.Error() == "key not found" {
set = refreshJWKS(ctx, uri)
key, err = jwk.FindPublicKey(set)
} Prevention
- Monitor JWKS endpoints for empty key arrays
- Refresh the key cache after rotations
- Never publish private-only JWKs; verify the JWKS contents after key generation
- Keep fixtures for signature verification updated
When it happens
Trigger: Calling FindPublicKey with a set that is empty, or that contains only private keys (which are excluded), or only keys filtered out by other means — returning `errors.New("key not found")` at jwk/helper.go:146.
Common situations: The JWKS endpoint returned an empty `keys` array; keys were rotated and the cached set has none matching; someone published a JWKS containing only private JWKs by mistake; a test fixture loads keys from the wrong file.
Related errors
- issuer URL must be set unless development mode is enabled
- issuer URL scheme must be HTTPS unless development mode is e
- failed to set token lifespans due to failed client type asse
- a secret for signing HMAC-SHA512/256 is expected to be defin
- Token used before issued
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/7192ebad215b8b47.
Report an issue: GitHub.