{"record":{"id":"8c0148f3c9bcd07d","repo":"jwtk/jjwt","slug":"malformed-jwk-set-json-t-getmessage","errorCode":null,"errorMessage":"Malformed JWK Set JSON: ${t.getMessage()}","messagePattern":"Malformed JWK Set JSON: (.+?)","errorType":"exception","errorClass":"MalformedKeySetException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetDeserializer.java","lineNumber":31,"sourceCode":" * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage io.jsonwebtoken.impl.security;\n\nimport io.jsonwebtoken.impl.io.JsonObjectDeserializer;\nimport io.jsonwebtoken.io.Deserializer;\nimport io.jsonwebtoken.security.MalformedKeySetException;\n\npublic class JwkSetDeserializer extends JsonObjectDeserializer {\n\n    public JwkSetDeserializer(Deserializer<?> deserializer) {\n        super(deserializer, \"JWK Set\");\n    }\n\n    @Override\n    protected RuntimeException malformed(Throwable t) {\n        String msg = \"Malformed JWK Set JSON: \" + t.getMessage();\n        throw new MalformedKeySetException(msg, t);\n    }\n}\n","sourceCodeStart":13,"sourceCodeEnd":34,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/JwkSetDeserializer.java#L13-L34","documentation":"JwkSetDeserializer.malformed wraps any Throwable raised while deserializing JWK Set JSON into a MalformedKeySetException with the message \"Malformed JWK Set JSON: <cause>\". It signals the input JSON could not be parsed or did not satisfy JWK Set requirements.","triggerScenarios":"Calling the deserializer with JSON that is not a valid JWK Set: syntactically invalid JSON, JSON that is not an object, a missing \"keys\" array, or entries that fail validation during deserialization.","commonSituations":"JWKS endpoint returning an HTML error page instead of JSON; truncated response body; wrong URL configured for the issuer's JWKS; serving a single JWK object instead of a Set.","solutions":["Log/print the cause message to see the underlying parse problem and fix the JSON source.","Verify the JWKS endpoint returns application/json with a top-level object containing a \"keys\" array.","Re-fetch the document; check for proxies/CDN error pages replacing the JSON.","Validate the JSON with a linter or json parser before feeding it to the deserializer."],"exampleFix":"// before\nString body = new String(response.getBytes()); // may be HTML error page\nJwkSet set = deserialize(body);\n\n// after\nif (!body.trim().startsWith(\"{\")) {\n    throw new IllegalStateException(\"JWKS endpoint returned non-JSON: \" + body.substring(0, Math.min(100, body.length())));\n}\nJwkSet set = deserialize(body);","handlingStrategy":"try-catch","validationCode":"boolean isJsonObject(String s) {\n    try { new JSONTokener(s).nextValue(); return s.trim().startsWith(\"{\"); }\n    catch (JSONException e) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n    jwkSet = deserializer.deserialize(json);\n} catch (MalformedKeySetException e) {\n    logger.error(\"JWKS document invalid: {}\", e.getMessage());\n    // re-fetch from issuer or fail closed\n}","preventionTips":["Check HTTP content-type is application/json before parsing JWKS responses.","Detect HTML error pages (status != 200 or body not starting with '{') before deserializing.","Cache the last-known-good JWKS as a fallback."],"tags":["jwk","json","deserialization","malformed-json","jsonwebtoken"],"backgroundTag":"json-parse-error","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"}