jwtk/jjwt · error · io.jsonwebtoken.security.MalformedKeyException
JWK kty value cannot be empty.
Error message
JWK kty value cannot be empty.
What it means
Thrown by JwkConverter.applyFrom when a JWK's kty member is a String but empty. RFC 7517 requires kty to be a meaningful key-type identifier; an empty string cannot identify a key type, so the JWK is rejected as malformed (MalformedKeyException).
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JwkConverter.java:157
// 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()) {
Object key = entry.getKey();
Assert.notNull(key, "JWK map key cannot be null.");
if (!(key instanceof String)) {
String msg = "JWK map keys must be Strings. Encountered key '" + key + "' of type " +
key.getClass().getName() + ".";
throw new IllegalArgumentException(msg);
}
String skey = (String) key;
builder.add(skey, entry.getValue());
}
Jwk<?> jwk = builder.build();
if (desiredType.isInstance(jwk)) {
return desiredType.cast(jwk);View on GitHub (pinned to fb71496164)
Solutions
- Supply a valid kty value ("EC", "RSA", "oct", "OKP")
- Trim/default handling in the code that generates or forwards JWK JSON
- Validate the key JSON before passing it to the jjwt Jwks APIs
Example fix
// before
{"kty":"", "crv":"P-256", "x":"...", "y":"..."}
// after
{"kty":"EC", "crv":"P-256", "x":"...", "y":"..."} Defensive patterns
Strategy: validation
Validate before calling
String kty = (String) jwkMap.get("kty"); if (kty == null || kty.isBlank()) { throw new IllegalArgumentException("kty must be non-empty"); } Type guard
boolean hasTextKty(Map<String,?> m) { return m != null && m.get("kty") instanceof String s && !s.isBlank(); } Try / catch
try { jwk = parser.parse(json); } catch (MalformedKeyException e) { log.error("Empty kty: {}", e.getMessage()); } Prevention
- Never emit placeholder empty strings for kty
- Validate generated key documents with a schema check before use
When it happens
Trigger: JWK JSON such as {"kty":""} or {"kty":" "} passed to JWK parsing/conversion.
Common situations: Placeholder values left in generated config; field stripped by a template engine; upstream key provider returning empty kty.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- JWK is missing required kty parameter.
- JWK kty value cannot be null.
- JWK Set keys collection cannot be empty.
- RSA JWK 'oth' (Other Prime Info) element cannot be null.
- ${name()} is missing required ${param} value.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/593c6c14adc2e458.
Report an issue: GitHub.