jwtk/jjwt · error · UnsupportedJwtException

Unexpected Claims JWE.

Error message

Unexpected Claims JWE.

What it means

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.

Source

Thrown at api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java:198

     * @return any object to be used after inspecting the JWS, or {@code null} if no return value is necessary.
     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.
     */
    public T onDecryptedContent(Jwe<byte[]> jwe) {
        throw new UnsupportedJwtException("Unexpected content JWE.");
    }

    /**
     * Handles an encountered JWE message that has been authenticated and decrypted, and has a {@link Claims} payload.
     *
     * <p>The default implementation immediately throws an {@link UnsupportedJwtException}; it is expected that
     * subclasses will override this method if the application needs to support this type of JWT.</p>
     *
     * @param jwe the parsed authenticated and decrypted content JWE.
     * @return any object to be used after inspecting the JWE, or {@code null} if no return value is necessary.
     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.
     */
    public T onDecryptedClaims(Jwe<Claims> jwe) {
        throw new UnsupportedJwtException("Unexpected Claims JWE.");
    }
}

View on GitHub (pinned to fb71496164)

Solutions

  1. Override onDecryptedClaims in your SupportedJwtVisitor subclass to process Jwe<Claims> and return the desired value.
  2. Ensure the parser is configured with the correct decryption key and algorithms so the JWE decrypts and dispatches correctly.
  3. If Claims JWEs are not expected, reject them before parsing or filter by the token's header (typ/enc).
  4. Add tests covering encrypted Claims tokens to catch unimplemented visitor callbacks.

Example fix

// before
public class JwsOnlyVisitor extends SupportedJwtVisitor<MyType> {
    @Override public MyType onVerifiedClaims(Jws<Claims> jws) { return handle(jws.getPayload()); }
    // onDecryptedClaims not overridden -> throws on JWE
}
// after
public class JwsOnlyVisitor extends SupportedJwtVisitor<MyType> {
    @Override public MyType onVerifiedClaims(Jws<Claims> jws) { return handle(jws.getPayload()); }
    @Override public MyType onDecryptedClaims(Jwe<Claims> jwe) { return handle(jwe.getPayload()); }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the token is a 5-part JWE (encrypted Claims possible) before visitor dispatch
String[] parts = compact.split("\\.", -1);
boolean encryptedClaimsCandidate = parts.length == 5;
if (encryptedClaimsCandidate && !visitorHandlesDecryptedClaims) {
    throw new IllegalArgumentException("Encrypted Claims JWE not supported by this handler");
}

Type guard

boolean visitorHandlesDecryptedClaims(SupportedJwtVisitor<?> v) {
    try {
        return !SupportedJwtVisitor.class.equals(
            v.getClass().getMethod("onDecryptedClaims", Jwe.class).getDeclaringClass());
    } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    Jwe<Claims> jwe = Jwts.parser().decryptWith(key).build().parseEncryptedClaims(token);
} catch (UnsupportedJwtException e) {
    log.warn("Decrypted Claims JWE dispatched to a visitor without onDecryptedClaims", e);
    throw new SecurityException("Claims JWE not supported by this visitor", e);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/f26c3fb314aba12f. Report an issue: GitHub.