jwtk/jjwt · error · IllegalArgumentException
JWK Set map keys must be Strings. Encountered key '${key}' o
Error message
JWK Set map keys must be Strings. Encountered key '${key}' of type ${key.getClass().getName()} What it means
Thrown by JwkSetConverter.applyFrom when converting a Map representation of a JWK Set whose top-level keys are not Strings. JWK Set maps must have JSON-string keys (like "keys", "kty"); any non-String key means the input map is not a valid JWK Set representation. The library fails fast with IllegalArgumentException naming the offending key and its Java type.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java:112
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);
}
int size = Collections.size((Collection<?>) val);
if (size == 0) {
String msg = "JWK Set " + PARAM + " collection cannot be empty.";
throw new MalformedKeySetException(msg);
}
// Copy values so we don't mutate the original input
Map<String, Object> src = new LinkedHashMap<>(Collections.size((Map<?, ?>) o));
for (Map.Entry<?, ?> entry : ((Map<?, ?>) o).entrySet()) {
Object key = Assert.notNull(entry.getKey(), "JWK Set map key cannot be null.");
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) {View on GitHub (pinned to fb71496164)
Solutions
- Convert all map keys to Strings before passing the map (e.g. String.valueOf(key)).
- Inspect the offending key printed in the message and remove/fix the non-String entry in the source map.
- If the data comes from another format (YAML/DB), transform it to a Map<String, Object> first.
- If you need non-String identifiers, store them as values inside the JWK entries instead of as map keys.
Example fix
// before Map<Object, Object> bad = new LinkedHashMap<>(); bad.put(1234, jwkEntry); JwkSetConverter.getInstance().applyFrom(bad); // after Map<String, Object> good = new LinkedHashMap<>(); good.put(String.valueOf(1234), jwkEntry); JwkSetConverter.getInstance().applyFrom(good);
Defensive patterns
Strategy: validation
Validate before calling
boolean isValidJwkSetMap(Map<?, ?> m) {
return m != null && m.keySet().stream().allMatch(k -> k instanceof String);
} Type guard
boolean allStringKeys(Map<?, ?> m) {
return m.keySet().stream().allMatch(k -> k instanceof String);
} Try / catch
try {
converter.applyFrom(map);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("JWK Set map keys must be Strings")) {
// normalize keys and retry
} else throw e;
} Prevention
- Always declare maps as Map<String, Object> when building JWK data.
- Normalize keys from external sources (YAML, DB) with String.valueOf before conversion.
- Add a unit test asserting keySet types for any map you feed to JWK parsing.
When it happens
Trigger: Calling JwkSetConverter.applyFrom(o) (directly or via API that parses a JWK Set from a Map) with a LinkedHashMap or other Map containing non-String keys, e.g. an Integer or enum key mixed into the map.
Common situations: Building a JWK Set map programmatically with non-String keys (Integer ids, Key objects, enums); deserializing from a format like YAML or a database row where keys were not normalized to Strings; passing an internal map that was never meant to be a JWK Set.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unsupported JwkContext.
- JWK Set keys[${i}]: ${e.getMessage()}
- Malformed JWK Set JSON: ${t.getMessage()}
- ${message}
- String value is not a JWT NumericDate, nor is it ISO-8601-fo
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/506f77b0d62ef787.
Report an issue: GitHub.