{"record":{"id":"f26c3fb314aba12f","repo":"jwtk/jjwt","slug":"unexpected-claims-jwe","errorCode":null,"errorMessage":"Unexpected Claims JWE.","messagePattern":"Unexpected Claims JWE\\.","errorType":"exception","errorClass":"UnsupportedJwtException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java","lineNumber":198,"sourceCode":"     * @return any object to be used after inspecting the JWS, or {@code null} if no return value is necessary.\n     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.\n     */\n    public T onDecryptedContent(Jwe<byte[]> jwe) {\n        throw new UnsupportedJwtException(\"Unexpected content JWE.\");\n    }\n\n    /**\n     * Handles an encountered JWE message that has been authenticated and decrypted, and has a {@link Claims} payload.\n     *\n     * <p>The default implementation immediately throws an {@link UnsupportedJwtException}; it is expected that\n     * subclasses will override this method if the application needs to support this type of JWT.</p>\n     *\n     * @param jwe the parsed authenticated and decrypted content JWE.\n     * @return any object to be used after inspecting the JWE, or {@code null} if no return value is necessary.\n     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.\n     */\n    public T onDecryptedClaims(Jwe<Claims> jwe) {\n        throw new UnsupportedJwtException(\"Unexpected Claims JWE.\");\n    }\n}\n","sourceCodeStart":180,"sourceCodeEnd":201,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java#L180-L201","documentation":"SupportedJwtVisitor.onDecryptedClaims is the default callback for a JWE that has been authenticated, decrypted, and whose payload is a Claims JSON object. The base implementation throws UnsupportedJwtException, expecting subclasses to override it. Hitting it means a decrypted Claims JWE was dispatched to a visitor that does not implement handling for that token type.","triggerScenarios":"Parsing an encrypted token whose plaintext payload is Claims (built with Jwts.builder().claims()...encryptWith(...)) via a parser whose visitor lacks an onDecryptedClaims override; decryption succeeds, then the dispatch throws.","commonSituations":"Consumers migrating from signed Claims JWS to encrypted Claims JWE whose visitors only overrode onVerifiedClaims; shared parsing infrastructure that handles JWS but not JWE; omitted override after adding encryption to a token flow.","solutions":["Override onDecryptedClaims in your SupportedJwtVisitor subclass to process Jwe<Claims> and return the desired value.","Ensure the parser is configured with the correct decryption key and algorithms so the JWE decrypts and dispatches correctly.","If Claims JWEs are not expected, reject them before parsing or filter by the token's header (typ/enc).","Add tests covering encrypted Claims tokens to catch unimplemented visitor callbacks."],"exampleFix":"// before\npublic class JwsOnlyVisitor extends SupportedJwtVisitor<MyType> {\n    @Override public MyType onVerifiedClaims(Jws<Claims> jws) { return handle(jws.getPayload()); }\n    // onDecryptedClaims not overridden -> throws on JWE\n}\n// after\npublic class JwsOnlyVisitor extends SupportedJwtVisitor<MyType> {\n    @Override public MyType onVerifiedClaims(Jws<Claims> jws) { return handle(jws.getPayload()); }\n    @Override public MyType onDecryptedClaims(Jwe<Claims> jwe) { return handle(jwe.getPayload()); }\n}","handlingStrategy":"try-catch","validationCode":"// Confirm the token is a 5-part JWE (encrypted Claims possible) before visitor dispatch\nString[] parts = compact.split(\"\\\\.\", -1);\nboolean encryptedClaimsCandidate = parts.length == 5;\nif (encryptedClaimsCandidate && !visitorHandlesDecryptedClaims) {\n    throw new IllegalArgumentException(\"Encrypted Claims JWE not supported by this handler\");\n}","typeGuard":"boolean visitorHandlesDecryptedClaims(SupportedJwtVisitor<?> v) {\n    try {\n        return !SupportedJwtVisitor.class.equals(\n            v.getClass().getMethod(\"onDecryptedClaims\", Jwe.class).getDeclaringClass());\n    } catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    Jwe<Claims> jwe = Jwts.parser().decryptWith(key).build().parseEncryptedClaims(token);\n} catch (UnsupportedJwtException e) {\n    log.warn(\"Decrypted Claims JWE dispatched to a visitor without onDecryptedClaims\", e);\n    throw new SecurityException(\"Claims JWE not supported by this visitor\", e);\n}","preventionTips":["Override onDecryptedClaims whenever encrypted claims tokens are part of your flows","Prefer parseEncryptedClaims when the token type is known instead of generic visitor parsing","Test visitors against all four token shapes: unsecured, JWS, JWE, claims vs content payloads","Keep a checklist of SupportedJwtVisitor callbacks to override when adding new token types"],"tags":["java","jwt","jjwt","jwe","claims","unsupported-jwt"],"backgroundTag":"unsupported-operation","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"}