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.
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)
Solutions
- Override onVerifiedContent in your SupportedJwtVisitor subclass to process Jws<byte[]> and return the desired value.
- If the payload should be Claims, change the producer to use claim-based builder APIs (Jwts.builder().claims()...) so onVerifiedClaims is dispatched instead.
- If content JWSs are not expected, reject the token and validate the producer/endpoint sending it.
- 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
- Implement onVerifiedContent whenever your visitor may see non-Claims signed payloads
- Agree on token types (typ header) between producers and consumers
- Use the specific parse method (parseClaimsJws vs content parse) matching the expected payload
- Unit-test the visitor against every token shape your system exchanges
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
- Unexpected Claims JWS.
- Unexpected unsecured Claims JWT.
- Unexpected content JWE.
- Unexpected Claims JWE.
- ${message}
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/2f3118b59e616295.
Report an issue: GitHub.