jwtk/jjwt · error · IllegalArgumentException
${message}${subType} is not assignable to ${superType}
Error message
${message}${subType} is not assignable to ${superType} What it means
Thrown by Assert.isAssignable(Class superType, Class subType, String) when subType is null or superType.isAssignableFrom(subType) is false, i.e. the subType class cannot be used where superType is expected. Raises IllegalArgumentException with message + '<subType> is not assignable to <superType>'.
Source
Thrown at api/src/main/java/io/jsonwebtoken/lang/Assert.java:444
isAssignable(superType, subType, "");
}
/**
* Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
* <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
*
* @param superType the super type to check against
* @param subType the sub type to check
* @param message a message which will be prepended to the message produced by
* the function itself, and which may be used to provide context. It should
* normally end in a ": " or ". " so that the function generate message looks
* ok when prepended to it.
* @throws IllegalArgumentException if the classes are not assignable
*/
public static void isAssignable(Class superType, Class subType, String message) {
notNull(superType, "Type to check against must not be null");
if (subType == null || !superType.isAssignableFrom(subType)) {
throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
}
}
/**
* Asserts that a specified {@code value} is equal to the given {@code requirement}, throwing
* an {@link IllegalArgumentException} with the given message if not.
*
* @param <T> the type of argument
* @param value the value to check
* @param requirement the requirement that {@code value} must be greater than
* @param msg the message to use for the {@code IllegalArgumentException} if thrown.
* @return {@code value} if greater than the specified {@code requirement}.
* @since 0.12.0
*/
public static <T extends Comparable<T>> T eq(T value, T requirement, String msg) {
if (compareTo(value, requirement) != 0) {
throw new IllegalArgumentException(msg);
}View on GitHub (pinned to fb71496164)
Solutions
- Make the subType class extend/implement the required superType
- Register the correct class that does implement the interface
- Verify with SuperType.class.isAssignableFrom(SubType.class) before calling
- Check for duplicate/conflicting library versions causing wrong classes to load
Example fix
// before
class MyCompressor { /* does not implement Compressor */ }
Jwts.registry().compressor("MYC", MyCompressor.class); // throws
// after
class MyCompressor implements Compressor { /* ... */ }
Jwts.registry().compressor("MYC", MyCompressor.class); Defensive patterns
Strategy: validation
Validate before calling
if (subType == null || !superType.isAssignableFrom(subType)) {
throw new IllegalArgumentException(subType + " must implement/extend " + superType);
} Type guard
// compile-time alternative: declare generics instead of Class checks
<T extends Compressor> void register(Class<T> subType) { /* cannot be wrong */ } Try / catch
try {
Assert.isAssignable(Compressor.class, myClass, "bad registration: ");
} catch (IllegalArgumentException e) {
log.error("Registration rejected: {}", e.getMessage());
throw e;
} Prevention
- Implement the required interface before registering a custom class
- Let generics enforce the bound at compile time where possible
- Smoke-test custom registrations in unit tests to catch hierarchy mistakes
When it happens
Trigger: Passing a Class object (not an instance) that does not extend/implement the required supertype, e.g. registering a custom implementation class with JJWT's registry/factory (custom compressor, serializer, key algorithm) where the class has the wrong hierarchy.
Common situations: Typo or wrong class supplied to a plugin registration point; refactoring removed an interface a custom class used to implement; copying a registration example with a different class; classloader split exposing different Class objects than expected at runtime.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- ${message}Object of class [${objClassName}] must be an insta
- JWT Claim '<expectedClaimName>' was expected to be a Date, b
- JWK kty value must be a String. Type found: ${type}
- JWK map keys must be Strings. Encountered key '${key}' of ty
- Value must be a Map<String,?> (JSON Object). Type found: ${t
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/8e8ecbb7c7e1230c.
Report an issue: GitHub.