{"record":{"id":"506f77b0d62ef787","repo":"jwtk/jjwt","slug":"jwk-set-map-keys-must-be-strings-encountered-key","errorCode":null,"errorMessage":"JWK Set map keys must be Strings. Encountered key '${key}' of type ${key.getClass().getName()}","messagePattern":"JWK Set map keys must be Strings\\. Encountered key '(.+?)' of type (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java","lineNumber":112,"sourceCode":"        if (!(val instanceof Collection)) {\n            String msg = \"JWK Set \" + PARAM + \" value must be a Collection (JSON Array). Type found: \" +\n                    val.getClass().getName();\n            throw new MalformedKeySetException(msg);\n        }\n        int size = Collections.size((Collection<?>) val);\n        if (size == 0) {\n            String msg = \"JWK Set \" + PARAM + \" collection cannot be empty.\";\n            throw new MalformedKeySetException(msg);\n        }\n\n        // Copy values so we don't mutate the original input\n        Map<String, Object> src = new LinkedHashMap<>(Collections.size((Map<?, ?>) o));\n        for (Map.Entry<?, ?> entry : ((Map<?, ?>) o).entrySet()) {\n            Object key = Assert.notNull(entry.getKey(), \"JWK Set map key cannot be null.\");\n            if (!(key instanceof String)) {\n                String msg = \"JWK Set map keys must be Strings. Encountered key '\" + key + \"' of type \" +\n                        key.getClass().getName();\n                throw new IllegalArgumentException(msg);\n            }\n            String skey = (String) key;\n            src.put(skey, entry.getValue());\n        }\n\n        Set<Jwk<?>> jwks = new LinkedHashSet<>(size);\n        int i = 0; // keep track of which element fails (if any)\n        for (Object candidate : ((Collection<?>) val)) {\n            try {\n                Jwk<?> jwk = JWK_CONVERTER.applyFrom(candidate);\n                jwks.add(jwk);\n            } catch (UnsupportedKeyException e) {\n                if (!ignoreUnsupported) {\n                    String msg = \"JWK Set keys[\" + i + \"]: \" + e.getMessage();\n                    throw new UnsupportedKeyException(msg, e);\n                }\n            } catch (IllegalArgumentException | KeyException e) {\n                if (!ignoreUnsupported) {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java#L94-L130","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nMap<Object, Object> bad = new LinkedHashMap<>();\nbad.put(1234, jwkEntry);\nJwkSetConverter.getInstance().applyFrom(bad);\n\n// after\nMap<String, Object> good = new LinkedHashMap<>();\ngood.put(String.valueOf(1234), jwkEntry);\nJwkSetConverter.getInstance().applyFrom(good);","handlingStrategy":"validation","validationCode":"boolean isValidJwkSetMap(Map<?, ?> m) {\n    return m != null && m.keySet().stream().allMatch(k -> k instanceof String);\n}","typeGuard":"boolean allStringKeys(Map<?, ?> m) {\n    return m.keySet().stream().allMatch(k -> k instanceof String);\n}","tryCatchPattern":"try {\n    converter.applyFrom(map);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"JWK Set map keys must be Strings\")) {\n        // normalize keys and retry\n    } else throw e;\n}","preventionTips":["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."],"tags":["jwk","map-validation","illegal-argument","jsonwebtoken"],"backgroundTag":"invalid-argument-value","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}