jwtk/jjwt · error · UnsupportedKeyException
JWK Set keys[${i}]: ${e.getMessage()}
Error message
JWK Set keys[${i}]: ${e.getMessage()} What it means
When parsing a JWK Set, each candidate key entry is converted with JWK_CONVERTER.applyFrom. If conversion raises UnsupportedKeyException (an unsupported key type/algorithm) and ignoreUnsupported is false, this error wraps the original message with the entry index, e.g. "JWK Set keys[2]: ...". It lets callers know exactly which key in the set was unsupported.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java:127
if (!(key instanceof String)) {
String msg = "JWK Set map keys must be Strings. Encountered key '" + key + "' of type " +
key.getClass().getName();
throw new IllegalArgumentException(msg);
}
String skey = (String) key;
src.put(skey, entry.getValue());
}
Set<Jwk<?>> jwks = new LinkedHashSet<>(size);
int i = 0; // keep track of which element fails (if any)
for (Object candidate : ((Collection<?>) val)) {
try {
Jwk<?> jwk = JWK_CONVERTER.applyFrom(candidate);
jwks.add(jwk);
} catch (UnsupportedKeyException e) {
if (!ignoreUnsupported) {
String msg = "JWK Set keys[" + i + "]: " + e.getMessage();
throw new UnsupportedKeyException(msg, e);
}
} catch (IllegalArgumentException | KeyException e) {
if (!ignoreUnsupported) {
String msg = "JWK Set keys[" + i + "]: " + e.getMessage();
throw new MalformedKeySetException(msg, e);
}
}
i++;
}
// Replace the `keys` value with validated entries:
src.remove(PARAM.getId());
src.put(PARAM.getId(), jwks);
return new DefaultJwkSet(PARAM, src);
}
}
View on GitHub (pinned to fb71496164)
Solutions
- Upgrade jjwt to the latest version so more key types/algorithms are supported.
- Parse with ignoreUnsupported=true (e.g. via JwkSet parsing options) to skip unsupported keys instead of failing.
- Filter the JWKS response to only supported "kty" values before conversion.
- Check the wrapped message for keys[N] index to inspect and remove/replace the offending entry.
Example fix
// before JwkSet jwks = Jwks.set().add(rawMap).build(); // strict: throws on unsupported kty // after JwkSet jwks = Jwks.set().add(rawMap).ignoreUnsupported(true).build(); // skips unsupported keys
Defensive patterns
Strategy: try-catch
Validate before calling
Set<String> supported = Set.of("EC", "RSA", "oct", "OKP");
boolean allSupported(List<Map<String, Object>> keys) {
return keys.stream().allMatch(k -> supported.contains(k.get("kty")));
} Try / catch
try {
jwkSet = parse(json);
} catch (UnsupportedKeyException e) {
// optionally re-parse with ignoreUnsupported(true) or upgrade jjwt
logger.warn("Skipping unsupported JWK: {}", e.getMessage());
} Prevention
- Pin the latest jjwt version so new key types are supported.
- Check your IdP's JWKS for exotic kty values before strict parsing.
- Prefer ignoreUnsupported=true for verifying-only JWKS consumption.
When it happens
Trigger: Parsing/converting a JWK Set whose keys array contains an entry with an unsupported "kty" or algorithm, with ignoreUnsupported=false (default strict mode).
Common situations: JWK Set published by an identity provider includes key types this jjwt version does not support (e.g. oct-pair, AKP, unusual EC curves, or keys requiring a newer jjwt release); strict parsing of an OP's JWKS endpoint that mixes supported and unsupported keys.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unrecognized JWA EC curve id '${jwaCurveId}'
- JWK Set map keys must be Strings. Encountered key '${key}' o
- Malformed JWK Set JSON: ${t.getMessage()}
- ${String.format(PUB_EXPONENT_EX_MSG, KeysBridge.toString(key
- unsupportedKey(key, e)
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/4694d75bce61895c.
Report an issue: GitHub.