Skip to content
ecdsa.com
PyJWT (Python)JWKS and key discovery

Error message

Unable to find a signing key that matches: "2026-10"

Also printed as

  • jwt.exceptions.PyJWKClientError: Unable to find a signing key that matches: "2026-10"
  • Unable to find a signing key that matches: "None"

The quoted value is the token's `kid`; `"None"` means the header has no `kid`.

PyJWT (Python) — jwt.exceptions.PyJWKClientError from PyJWKClient.get_signing_key_from_jwt

What it means

`PyJWKClient` fetched the key set and found no signing key whose `kid` equals the token header's `kid` (shown in quotes). PyJWKClient refreshes the key set once when a `kid` is unknown, so the key really is not published at that URL right now. `"None"` in quotes means the token has no `kid` at all.

Why it happens

How to fix it

  1. 1.

    Compare the token's kid with the loaded keys

    `get_signing_keys(refresh=True)` shows exactly which keys PyJWKClient can use. If the token's `kid` is missing there, the issuer or the URL is the problem, not your code.

    python
    print(jwt.get_unverified_header(token).get("kid"))
    for key in client.get_signing_keys(refresh=True):
        print(key.key_id, key.algorithm_name)
  2. 2.

    Reuse one PyJWKClient

    Creating the client per request disables caching and hits the issuer on every call. A long-lived client with a key cache still refetches when a new `kid` appears.

    python
    from jwt import PyJWKClient
    
    # Module level: one client, cached keys, refetch on an unknown kid.
    JWKS = PyJWKClient("https://issuer.example.com/.well-known/jwks.json", cache_keys=True, lifespan=600)
    
    def verify(token: str) -> dict:
        signing_key = JWKS.get_signing_key_from_jwt(token)
        return jwt.decode(token, signing_key.key, algorithms=["ES256"], audience="https://api.example.com")

Related errors

Browse the full signature error database