{"record":{"id":"b4e0a8d646652961","repo":"jwtk/jjwt","slug":"jwk-kty-value-must-be-a-string-type-found-type","errorCode":null,"errorMessage":"JWK kty value must be a String. Type found: ${type}","messagePattern":"JWK kty value must be a String\\. Type found: (.+?)","errorType":"validation","errorClass":"io.jsonwebtoken.security.MalformedKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/JwkConverter.java","lineNumber":152,"sourceCode":"            throw new IllegalArgumentException(msg);\n        }\n        final Map<?, ?> map = Collections.immutable((Map<?, ?>) o);\n\n        Parameter<String> param = AbstractJwk.KTY;\n        // mandatory for all JWKs: https://datatracker.ietf.org/doc/html/rfc7517#section-4.1\n        // no need for builder param type conversion overhead if this isn't present:\n        if (Collections.isEmpty(map) || !map.containsKey(param.getId())) {\n            String msg = \"JWK is missing required \" + param + \" parameter.\";\n            throw new MalformedKeyException(msg);\n        }\n        Object val = map.get(param.getId());\n        if (val == null) {\n            String msg = \"JWK \" + param + \" value cannot be null.\";\n            throw new MalformedKeyException(msg);\n        }\n        if (!(val instanceof String)) {\n            String msg = \"JWK \" + param + \" value must be a String. Type found: \" + val.getClass().getName();\n            throw new MalformedKeyException(msg);\n        }\n        String kty = (String) val;\n        if (!Strings.hasText(kty)) {\n            String msg = \"JWK \" + param + \" value cannot be empty.\";\n            throw new MalformedKeyException(msg);\n        }\n\n        DynamicJwkBuilder<?, ?> builder = this.supplier.get();\n        for (Map.Entry<?, ?> entry : map.entrySet()) {\n            Object key = entry.getKey();\n            Assert.notNull(key, \"JWK map key cannot be null.\");\n            if (!(key instanceof String)) {\n                String msg = \"JWK 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            builder.add(skey, entry.getValue());","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/JwkConverter.java#L134-L170","documentation":"Thrown by JwkConverter.applyFrom when the kty (key type) member of a JWK JSON object is present but is not a JSON string. RFC 7517 §4.1 requires kty to be a case-sensitive string (e.g. \"oct\", \"RSA\", \"EC\", \"OKP\"), so a non-String value marks the JWK as malformed and conversion fails with MalformedKeyException.","triggerScenarios":"Passing a map where kty is a non-String object (e.g. a Map, List, enum object, or number) into JWK conversion.","commonSituations":"Programmatically constructed maps where kty was set to a custom key-type enum instead of its String value; custom deserializers producing non-String values.","solutions":["Set kty as a plain String (\"RSA\", \"EC\", \"oct\", \"OKP\")","If using an enum, pass enum.name() or toString() instead of the enum instance","Fix custom deserializers that map kty to non-String types"],"exampleFix":"// before\nMap<String,Object> jwk = Map.of(\"kty\", KeyType.RSA, \"n\", n, \"e\", e);\n// after\nMap<String,Object> jwk = Map.of(\"kty\", KeyType.RSA.name(), \"n\", n, \"e\", e);","handlingStrategy":"type-guard","validationCode":"if (!(jwkMap.get(\"kty\") instanceof String)) { throw new IllegalArgumentException(\"kty must be a String\"); }","typeGuard":"String ktyOrNull(Map<String,?> m) { Object v = m == null ? null : m.get(\"kty\"); return v instanceof String s ? s : null; }","tryCatchPattern":"try { jwk = Jwks.builder().build(); } catch (MalformedKeyException e) { log.error(\"kty must be a String: {}\", e.getMessage()); }","preventionTips":["Use enum.name() when mapping key-type enums to JWK fields","Keep JWK maps strictly Map<String,Object> with JSON-compatible types"],"tags":["jwt","jwk","type-mismatch"],"backgroundTag":"type-mismatch","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"}