jwtk/jjwt · error · java.lang.IllegalArgumentException
Value must be a Map<String,?> (JSON Object). Type found: ${t
Error message
Value must be a Map<String,?> (JSON Object). Type found: ${type}. What it means
JwkSetConverter.applyFrom requires its input to be a Map (JSON Object) representing a JWK Set, or an existing JwkSet. If the value is neither, IllegalArgumentException is thrown naming the actual type found.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java:79
public boolean isIgnoreUnsupported() {
return ignoreUnsupported;
}
@Override
public Object applyTo(JwkSet jwkSet) {
return jwkSet;
}
@Override
public JwkSet applyFrom(Object o) {
Assert.notNull(o, "Value cannot be null.");
if (o instanceof JwkSet) {
return (JwkSet) o;
}
if (!(o instanceof Map)) {
String msg = "Value must be a Map<String,?> (JSON Object). Type found: " + o.getClass().getName() + ".";
throw new IllegalArgumentException(msg);
}
final Map<?, ?> m = Collections.immutable((Map<?, ?>) o);
// mandatory for all JWK Sets: https://datatracker.ietf.org/doc/html/rfc7517#section-5
// no need for builder parameter type conversion overhead if this isn't present:
if (Collections.isEmpty(m) || !m.containsKey(PARAM.getId())) {
String msg = "Missing required " + PARAM + " parameter.";
throw new MalformedKeySetException(msg);
}
Object val = m.get(PARAM.getId());
if (val == null) {
String msg = "JWK Set " + PARAM + " value cannot be null.";
throw new MalformedKeySetException(msg);
}
if (!(val instanceof Collection)) {
String msg = "JWK Set " + PARAM + " value must be a Collection (JSON Array). Type found: " +
val.getClass().getName();
throw new MalformedKeySetException(msg);View on GitHub (pinned to fb71496164)
Solutions
- Pass the full JWKS document as a Map: {"keys":[...]} (parse the JSON string first if needed)
- If you have a List of keys, wrap it: Map.of("keys", keyList)
- Use the appropriate Jwks parser API that accepts raw JSON text rather than pre-conversion
Example fix
// before
jwkSetConverter.applyFrom(keysArray); // List, not Map
// after
jwkSetConverter.applyFrom(Map.of("keys", keysArray)); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof Map)) { throw new IllegalArgumentException("JWK Set input must be a Map"); } Type guard
boolean isJwkSetShape(Object o) { return o instanceof JwkSet || (o instanceof Map<?,?> m && m.containsKey("keys")); } Try / catch
try { JwkSet set = jwkSetConverter.applyFrom(obj); } catch (IllegalArgumentException e) { log.error("Not a JWK Set object: {}", e.getMessage()); } Prevention
- Parse JSON text into a Map before JWK Set conversion
- Pass the full {"keys":[...]} document, not the inner array
When it happens
Trigger: Passing a String, List, InputStream, or other non-Map object directly to JWK Set conversion (e.g. passing a parsed 'keys' array instead of the wrapping object).
Common situations: Passing the raw JWKS 'keys' array instead of the full {"keys":[...]} document; passing unparsed JSON text instead of a parsed Map.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- JWK Set keys value must be a Collection (JSON Array). Type f
- ${message}Object of class [${objClassName}] must be an insta
- ${message}${subType} is not assignable to ${superType}
- JWT Claim '<expectedClaimName>' was expected to be a Date, b
- JWK kty value must be a String. Type found: ${type}
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/bd81cfbe3c720494.
Report an issue: GitHub.