{"record":{"id":"bbb453b8054dc3d2","repo":"jwtk/jjwt","slug":"jwk-set-keys-value-must-be-a-collection-json-arra","errorCode":null,"errorMessage":"JWK Set keys value must be a Collection (JSON Array). Type found: ${type}","messagePattern":"JWK Set keys value must be a Collection \\(JSON Array\\)\\. Type found: (.+?)","errorType":"validation","errorClass":"io.jsonwebtoken.security.MalformedKeySetException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java","lineNumber":97,"sourceCode":"            throw new IllegalArgumentException(msg);\n        }\n        final Map<?, ?> m = Collections.immutable((Map<?, ?>) o);\n\n        // mandatory for all JWK Sets: https://datatracker.ietf.org/doc/html/rfc7517#section-5\n        // no need for builder parameter type conversion overhead if this isn't present:\n        if (Collections.isEmpty(m) || !m.containsKey(PARAM.getId())) {\n            String msg = \"Missing required \" + PARAM + \" parameter.\";\n            throw new MalformedKeySetException(msg);\n        }\n        Object val = m.get(PARAM.getId());\n        if (val == null) {\n            String msg = \"JWK Set \" + PARAM + \" value cannot be null.\";\n            throw new MalformedKeySetException(msg);\n        }\n        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());","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetConverter.java#L79-L115","documentation":"Thrown by JwkSetConverter.applyFrom when the keys member of a JWK Set is present and non-null but is not a JSON Array (Collection). RFC 7517 §5 requires keys to be an array of JWK objects, so any other JSON type marks the set malformed and conversion fails with MalformedKeySetException.","triggerScenarios":"JWKS input where \"keys\" is a single JWK object (Map) instead of an array, or a JSON string.","commonSituations":"Hand-written JWKS with a single key written as an object rather than a one-element array; custom serializers flattening single-element arrays.","solutions":["Wrap the single JWK in a JSON array: \"keys\":[{...}]","Fix the serializer/deserializer so keys is always an array","Validate the JWKS shape before passing it to jjwt"],"exampleFix":"// before\n{\"keys\":{\"kty\":\"RSA\",\"n\":\"...\",\"e\":\"AQAB\"}}\n// after\n{\"keys\":[{\"kty\":\"RSA\",\"n\":\"...\",\"e\":\"AQAB\"}]}","handlingStrategy":"type-guard","validationCode":"if (!(m.get(\"keys\") instanceof Collection)) { throw new IllegalArgumentException(\"'keys' must be a JSON array\"); }","typeGuard":"boolean keysIsArray(Map<?,?> m) { return m != null && m.get(\"keys\") instanceof Collection<?>; }","tryCatchPattern":"try { jwkSet = jwkSetConverter.applyFrom(map); } catch (MalformedKeySetException e) { log.error(\"keys must be an array: {}\", e.getMessage()); }","preventionTips":["Always serialize single keys as a one-element array","Round-trip JWKS documents through your serializer in tests"],"tags":["jwt","jwks","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-14T11:17:12.474Z"}