jwtk/jjwt · error · UnsupportedJwtException
Unexpected Claims JWS.
Error message
Unexpected Claims JWS.
What it means
SupportedJwtVisitor.onVerifiedClaims is the default callback for a JWS that has been cryptographically verified and whose payload is a Claims JSON object. The base class throws UnsupportedJwtException by default, expecting a subclass to override this method. Hitting it means your parser dispatched a verified Claims JWS to a visitor that does not handle that token type.
Source
Thrown at api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java:144
* @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.");
}
/**
* Handles an encountered JSON Web Encryption (aka 'JWE') message that has been authenticated and decrypted by
* delegating to either {@link #onDecryptedContent(Jwe)} or {@link #onDecryptedClaims(Jwe)} depending on the
* payload type.
*
* @param jwe the parsed authenticated and decrypted JWE.
* @return the value returned by either {@link #onDecryptedContent(Jwe)} or {@link #onDecryptedClaims(Jwe)}
* depending on the payload type.
* @throws UnsupportedJwtException if the payload is neither a {@code byte[]} nor {@code Claims}, or either
* delegate method throws the same.
*/
@SuppressWarnings("unchecked")
@Override
public T visit(Jwe<?> jwe) {
Assert.notNull(jwe, "JWE cannot be null.");
Object payload = jwe.getPayload();View on GitHub (pinned to fb71496164)
Solutions
- Override onVerifiedClaims in your SupportedJwtVisitor subclass to inspect and return data from Jws<Claims>.
- Confirm the parse call matches the token type (use parseClaimsJws or equivalent instead of a generic visitor parse if Claims are the target).
- If Claims JWSs are not supported in this code path, reject the token upstream before parsing.
- Add a test that parses a signed Claims token through the visitor to catch missing overrides early.
Example fix
// before
public class ContentOnlyVisitor extends SupportedJwtVisitor<MyType> {
@Override public MyType onVerifiedContent(Jws<byte[]> jws) { return handle(jws); }
// onVerifiedClaims not overridden -> throws
}
// after
public class ContentOnlyVisitor extends SupportedJwtVisitor<MyType> {
@Override public MyType onVerifiedContent(Jws<byte[]> jws) { return handle(jws); }
@Override public MyType onVerifiedClaims(Jws<Claims> jws) { return handleClaims(jws.getPayload()); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the visitor subclass overrides onVerifiedClaims before wiring it into the parser
Class<? extends SupportedJwtVisitor<?>> c = visitor.getClass();
boolean overridden = !SupportedJwtVisitor.class.equals(
c.getMethod("onVerifiedClaims", Jws.class).getDeclaringClass()); Type guard
boolean visitorHandlesClaimsJws(SupportedJwtVisitor<?> v) {
try {
return !SupportedJwtVisitor.class.equals(
v.getClass().getMethod("onVerifiedClaims", Jws.class).getDeclaringClass());
} catch (NoSuchMethodException e) { return false; }
} Try / catch
try {
Jws<Claims> jws = Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
} catch (UnsupportedJwtException e) {
log.warn("Verified Claims JWS dispatched to a visitor without onVerifiedClaims", e);
throw new SecurityException("Claims JWS not supported by this visitor", e);
} Prevention
- Never instantiate SupportedJwtVisitor directly; always subclass and override the callbacks you expect
- Prefer typed parse methods (parseSignedClaims) over generic visitor dispatch when the token type is known
- Add a smoke test parsing a signed Claims token through each visitor in production use
- Review visitor subclasses when adding new token types to the system
When it happens
Trigger: Parsing a properly signed token containing a Claims payload (e.g. created with Jwts.builder().claims()...signWith(key)) through a parser/visitor that does not override onVerifiedClaims — for example a visitor written only for content JWSs or JWEs.
Common situations: Custom visitor subclasses that only implemented some callbacks; refactors where parse() (visitor-dispatch) replaced parseClaimsJws() but the visitor was never extended; shared generic parsing pipelines receiving Claims JWSs they never anticipated.
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 content JWS.
- Unexpected Claims JWE.
- Unexpected unsecured Claims JWT.
- Unexpected content JWE.
- ${message}
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/d64cea31942f34fc.
Report an issue: GitHub.