jwtk/jjwt · error · io.jsonwebtoken.security.MalformedKeyException

JWK is missing required kty parameter.

Error message

JWK is missing required kty parameter.

What it means

When converting a raw JSON map into a Jwk, JwkConverter.applyFrom requires the mandatory 'kty' (key type) parameter as defined by RFC 7517 section 4.1. If the map is empty or lacks the 'kty' key, a MalformedKeyException is thrown. This is a hard requirement for all JWKs regardless of algorithm.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JwkConverter.java:143

    public T applyFrom(Object o) {
        Assert.notNull(o, "JWK cannot be null.");
        if (desiredType.isInstance(o)) {
            return desiredType.cast(o);
        } else if (o instanceof Jwk<?>) {
            throw unexpectedIAE((Jwk<?>) o);
        }
        if (!(o instanceof Map)) {
            String msg = "JWK must be a Map<String,?> (JSON Object). Type found: " + o.getClass().getName() + ".";
            throw new IllegalArgumentException(msg);
        }
        final Map<?, ?> map = Collections.immutable((Map<?, ?>) o);

        Parameter<String> param = AbstractJwk.KTY;
        // mandatory for all JWKs: https://datatracker.ietf.org/doc/html/rfc7517#section-4.1
        // no need for builder param type conversion overhead if this isn't present:
        if (Collections.isEmpty(map) || !map.containsKey(param.getId())) {
            String msg = "JWK is missing required " + param + " parameter.";
            throw new MalformedKeyException(msg);
        }
        Object val = map.get(param.getId());
        if (val == null) {
            String msg = "JWK " + param + " value cannot be null.";
            throw new MalformedKeyException(msg);
        }
        if (!(val instanceof String)) {
            String msg = "JWK " + param + " value must be a String. Type found: " + val.getClass().getName();
            throw new MalformedKeyException(msg);
        }
        String kty = (String) val;
        if (!Strings.hasText(kty)) {
            String msg = "JWK " + param + " value cannot be empty.";
            throw new MalformedKeyException(msg);
        }

        DynamicJwkBuilder<?, ?> builder = this.supplier.get();
        for (Map.Entry<?, ?> entry : map.entrySet()) {

View on GitHub (pinned to fb71496164)

Solutions

  1. Add the required "kty" field (e.g. "EC", "RSA", "oct", "OKP") to the JWK JSON object
  2. Verify you are passing an individual JWK object, not a JWK Set or another structure
  3. If parsing a JWKS document, ensure each element of the "keys" array contains "kty"

Example fix

// before
{"k":"..."}
// after
{"kty":"oct","k":"..."}
Defensive patterns

Strategy: validation

Validate before calling

if (jwkMap == null || !jwkMap.containsKey("kty")) { throw new IllegalArgumentException("JWK JSON must contain a 'kty' field"); }

Type guard

boolean hasKty(Map<String,?> m) { return m != null && m.get("kty") instanceof String s && !s.isBlank(); }

Try / catch

try { Jwk<?> jwk = Jwks.parser().build().parse(json); } catch (MalformedKeyException e) { log.error("Invalid JWK: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Passing a JSON object/map without a 'kty' member to Jwks parsing/builder conversion APIs (e.g. io.jsonwebtoken.Jwks parsing a key that omits kty).

Common situations: Hand-written JWK JSON that omits kty; keys copied from sources that strip fields; wrong nested object passed (e.g. passing the JWK Set wrapper where an individual key is expected, or vice versa).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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