jwtk/jjwt · error · UnsupportedJwtException

Unexpected content JWS.

Error message

Unexpected content JWS.

What it means

SupportedJwtVisitor.onVerifiedContent is the default callback for a JWS (cryptographically verified token) whose payload is arbitrary content (byte[], not Claims JSON). The base implementation throws UnsupportedJwtException because the library assumes a specific visitor subclass; applications handling raw-payload JWSs must override this method. It indicates the token type received does not match what the visitor is configured to handle.

Solutions

  1. Override onVerifiedContent in your SupportedJwtVisitor subclass to process Jws<byte[]> and return the desired value.
  2. If the payload should be Claims, change the producer to use claim-based builder APIs (Jwts.builder().claims()...) so onVerifiedClaims is dispatched instead.
  3. If content JWSs are not expected, reject the token and validate the producer/endpoint sending it.
  4. Use the matching parse API (e.g. parseContentJws if available) so the intended callback is invoked.

Example fix

// before
SupportedJwtVisitor<MyType> visitor = new SupportedJwtVisitor<>() {}; // default throws
// after
SupportedJwtVisitor<MyType> visitor = new SupportedJwtVisitor<>() {
    @Override
    public MyType onVerifiedContent(Jws<byte[]> jws) {
        byte[] payload = jws.getPayload();
        return processSignedContent(payload);
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Decode header before parsing to learn the payload kind
String headerJson = new String(Base64.getUrlDecoder().decode(compact.split("\\.")[0]));
boolean isJwsWithClaims = headerJson.contains("\"JWT\""); // typ claim hint
if (!isJwsWithClaims && !visitorSupportsContentJws) {
    throw new IllegalArgumentException("Content JWS not supported by this handler");
}

Type guard

boolean isSignedContentJws(String token) {
    String[] p = token.split("\\.", -1);
    return p.length == 3 && !p[2].isEmpty(); // signed (has signature), payload type confirmed at parse time
}

Try / catch

try {
    result = Jwts.parser().verifyWith(key).build().parse(token);
} catch (UnsupportedJwtException e) {
    log.warn("Received a content JWS the visitor does not handle", e);
    throw new SecurityException("Unsupported JWS payload type", e);
}

Prevention

When it happens

Trigger: Parsing a signed compact token whose payload is not a Claims JSON object (e.g. arbitrary string/binary content) via a parser whose visitor does not override onVerifiedContent. E.g. calling parser.parse() on a JWS built with Jwts.builder().setContent(bytes, sigAlg, key).

Common situations: Exchanging opaque signed payloads between services; a developer expected Claims but the producer sent raw content; mixing parseClaimsJws with content-JWS tokens; generic token-handling middleware that lacks an onVerifiedContent override.

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/2f3118b59e616295. Report an issue: GitHub.

Appendix: source

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

            Assert.stateIsInstance(Claims.class, payload, "Unexpected payload data type: ");
            return onVerifiedClaims((Jws<Claims>) jws);
        }
    }

    /**
     * Handles an encountered JWS message that has been cryptographically verified/authenticated and has
     * a byte[] array payload. If the JWT creator has set the (optional) {@link Header#getContentType()} value, the
     * application may inspect that value to determine how to convert the byte array to the final type as desired.
     *
     * <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 jws the parsed verified/authenticated JWS.
     * @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 onVerifiedContent(Jws<byte[]> jws) {
        throw new UnsupportedJwtException("Unexpected content JWS.");
    }

    /**
     * Handles an encountered JWS message that has been cryptographically verified/authenticated 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 jws the parsed signed (and verified) Claims JWS
     * @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 onVerifiedClaims(Jws<Claims> jws) {
        throw new UnsupportedJwtException("Unexpected Claims JWS.");
    }

    /**

View on GitHub (pinned to fb71496164)