jwtk/jjwt · error · InvalidKeyException

Unable to create ${type.getSimpleName()} from JWK ${ctx}: ${

Error message

Unable to create ${type.getSimpleName()} from JWK ${ctx}: ${e.getMessage()}

What it means

AbstractFamilyJwkFactory.apply wraps exceptions thrown while converting a JWK context into a typed Jwk/Key. Any non-KeyException failure becomes an InvalidKeyException prefixed with the target type and JWK context summary. It indicates malformed or inconsistent JWK fields that broke key reconstruction.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AbstractFamilyJwkFactory.java:94

    protected String getKeyFactoryJcaName(final JwkContext<?> ctx) {
        String jcaName = KeysBridge.findAlgorithm(ctx.getKey());
        return Strings.hasText(jcaName) ? jcaName : getId();
    }

    protected <T extends Key> T generateKey(final JwkContext<?> ctx, final Class<T> type, final CheckedFunction<KeyFactory, T> fn) {
        String jcaName = getKeyFactoryJcaName(ctx);
        JcaTemplate template = new JcaTemplate(jcaName, ctx.getProvider(), ctx.getRandom());
        return template.withKeyFactory(new CheckedFunction<KeyFactory, T>() {
            @Override
            public T apply(KeyFactory instance) {
                try {
                    return fn.apply(instance);
                } catch (KeyException keyException) {
                    throw keyException; // propagate
                } catch (Exception e) {
                    String msg = "Unable to create " + type.getSimpleName() + " from JWK " + ctx + ": " + e.getMessage();
                    throw new InvalidKeyException(msg, e);
                }
            }
        });
    }

    @Override
    public final J createJwk(JwkContext<K> ctx) {
        Assert.notNull(ctx, "JwkContext argument cannot be null.");
        if (!supports(ctx)) { //should be asserted by caller, but assert just in case:
            String msg = "Unsupported JwkContext.";
            throw new IllegalArgumentException(msg);
        }
        K key = ctx.getKey();
        if (key != null) {
            ctx.setType(this.ktyValue);
            return createJwkFromKey(ctx);
        } else {
            return createJwkFromValues(ctx);

View on GitHub (pinned to fb71496164)

Solutions

  1. Validate that all JWK fields are valid base64url strings of the expected length for the curve/modulus.
  2. Confirm the 'kty' matches the concrete builder used (e.g. ECPublicJwkBuilder for EC keys).
  3. Catch InvalidKeyException and log the wrapped cause (e.getCause()) for the underlying failure.
  4. Regenerate or re-export the key if the material is corrupt.

Example fix

// before
try { Jwk<?> jwk = Jwks.parser().build().parse(json); }
catch (Exception e) { log.error(e.getMessage()); }
// after
try { Jwk<?> jwk = Jwks.parser().build().parse(json); }
catch (InvalidKeyException e) { log.error("JWK invalid", e.getCause()); }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check base64url decodability of JWK fields
Base64.getUrlDecoder().decode(jwk.getString("n"));

Try / catch

try { Jwk<?> jwk = factory.apply(ctx); }
catch (InvalidKeyException e) { log.error("JWK {} invalid: {}", e.getMessage(), e.getCause()); }

Prevention

When it happens

Trigger: Calling Jwks.builder().build() or parsing a JWK where an arithmetic/decoding error occurs inside the type-specific factory (e.g. base64url-decoded coordinates of the wrong length, BigInteger conversion failures).

Common situations: JWK JSON with truncated or non-base64url 'n'/'e'/'x'/'y' values; mismatched kty vs fields; copying keys between systems corrupting values.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/8101432dd8faf82e. Report an issue: GitHub.