ory/hydra · error
unable to find JSON Web Key with ID: %s
Error message
unable to find JSON Web Key with ID: %s
What it means
Fetcher.GetKey looks up the requested key ID (kid) in the cache after (possibly) fetching the remote JWKS. If the fetched key set contains no key whose KeyID equals kid, it errors with this message. The set was fetched fine; the specific kid simply is not published there.
Source
Thrown at oryx/jwksx/fetcher.go:73
var set jose.JSONWebKeySet
if err := json.NewDecoder(res.Body).Decode(&set); err != nil {
return nil, errors.WithStack(err)
}
for _, k := range set.Keys {
f.Lock()
f.keys[k.KeyID] = k
f.Unlock()
}
f.RLock()
defer f.RUnlock()
if k, ok := f.keys[kid]; ok {
return &k, nil
}
return nil, errors.Errorf("unable to find JSON Web Key with ID: %s", kid)
}
View on GitHub (pinned to 4174065ffb)
Solutions
- Refresh the key set (create a new Fetcher or clear the cache) in case it is stale relative to the signing key rotation.
- Verify the JWKS URL matches the issuer that actually signed the token (check token 'iss' and discovery 'jwks_uri').
- Compare the token header 'kid' against the kids in the fetched JWKS (jose.JSONWebKeySet) to confirm the mismatch.
- Ensure you are verifying a token from the right environment/tenant; cross-environment tokens will never match.
Example fix
// before key, err := fetcher.GetKey(tokenKid) // stale cache // after fetcher = jwksx.NewFetcher(remoteJWKSURL) // re-fetch fresh keys key, err := fetcher.GetKey(tokenKid)
Defensive patterns
Strategy: fallback
Validate before calling
set, _ := fetchRemoteJWKS(jwksURL)
if !containsKid(set.Keys, tokenHeader.Kid) {
return fmt.Errorf("kid %s not present at %s; check issuer/rotation", tokenHeader.Kid, jwksURL)
} Try / catch
key, err := fetcher.GetKey(kid)
if err != nil {
fetcher = jwksx.NewFetcher(remoteURL) // refresh cache once
key, err = fetcher.GetKey(kid)
if err != nil { return fmt.Errorf("unknown kid %q for issuer", kid) }
} Prevention
- Refresh the JWKS on unknown kid instead of failing permanently.
- Verify the token issuer matches the JWKS source.
- Keep a fallback of previously rotated public keys.
When it happens
Trigger: Calling Fetcher.GetKey(kid) (oryx/jwksx/fetcher.go:73) with a kid that does not exist in the remote JWKS — typically a kid taken from a token's JWT header that the fetched key set never contained.
Common situations: Verifying tokens signed with a rotated-out key after the JWKS was refreshed; using the wrong issuer's JWKS URL; stale local cache that was populated before rotation; tokens minted by a different environment (staging token verified against prod keys).
Related errors
- ErrUnableToFindKeyID
- jwt from authorization HTTP header is expecting string value
- header, body and signature must all be set
- Token is expired
- Token used before issued
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/fab63b81c5f3be4f.
Report an issue: GitHub.