{"record":{"id":"8e8ecbb7c7e1230c","repo":"jwtk/jjwt","slug":"message-subtype-is-not-assignable-to-supert","errorCode":null,"errorMessage":"${message}${subType} is not assignable to ${superType}","messagePattern":"(.+?)(.+?) is not assignable to (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/jsonwebtoken/lang/Assert.java","lineNumber":444,"sourceCode":"        isAssignable(superType, subType, \"\");\n    }\n\n    /**\n     * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.\n     * <pre class=\"code\">Assert.isAssignable(Number.class, myClass);</pre>\n     *\n     * @param superType the super type to check against\n     * @param subType   the sub type to check\n     * @param message   a message which will be prepended to the message produced by\n     *                  the function itself, and which may be used to provide context. It should\n     *                  normally end in a \": \" or \". \" so that the function generate message looks\n     *                  ok when prepended to it.\n     * @throws IllegalArgumentException if the classes are not assignable\n     */\n    public static void isAssignable(Class superType, Class subType, String message) {\n        notNull(superType, \"Type to check against must not be null\");\n        if (subType == null || !superType.isAssignableFrom(subType)) {\n            throw new IllegalArgumentException(message + subType + \" is not assignable to \" + superType);\n        }\n    }\n\n    /**\n     * Asserts that a specified {@code value} is equal to the given {@code requirement}, throwing\n     * an {@link IllegalArgumentException} with the given message if not.\n     *\n     * @param <T>         the type of argument\n     * @param value       the value to check\n     * @param requirement the requirement that {@code value} must be greater than\n     * @param msg         the message to use for the {@code IllegalArgumentException} if thrown.\n     * @return {@code value} if greater than the specified {@code requirement}.\n     * @since 0.12.0\n     */\n    public static <T extends Comparable<T>> T eq(T value, T requirement, String msg) {\n        if (compareTo(value, requirement) != 0) {\n            throw new IllegalArgumentException(msg);\n        }","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/api/src/main/java/io/jsonwebtoken/lang/Assert.java#L426-L462","documentation":"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>'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nclass MyCompressor { /* does not implement Compressor */ }\nJwts.registry().compressor(\"MYC\", MyCompressor.class); // throws\n// after\nclass MyCompressor implements Compressor { /* ... */ }\nJwts.registry().compressor(\"MYC\", MyCompressor.class);","handlingStrategy":"validation","validationCode":"if (subType == null || !superType.isAssignableFrom(subType)) {\n    throw new IllegalArgumentException(subType + \" must implement/extend \" + superType);\n}","typeGuard":"// compile-time alternative: declare generics instead of Class checks\n<T extends Compressor> void register(Class<T> subType) { /* cannot be wrong */ }","tryCatchPattern":"try {\n    Assert.isAssignable(Compressor.class, myClass, \"bad registration: \");\n} catch (IllegalArgumentException e) {\n    log.error(\"Registration rejected: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["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"],"tags":["jwt","type-mismatch","class-hierarchy"],"backgroundTag":"type-mismatch","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}