jwtk/jjwt · error · IllegalArgumentException

Object of class [ ] must be an instance of

Error message

${message}Object of class [${objClassName}] must be an instance of ${type}

What it means

Thrown by Assert.isInstanceOf(Class, Object, String) when the object is not an instance of the required type. The message concatenates the caller's prefix plus 'Object of class [X] must be an instance of Y'. JJWT uses this to enforce internal type contracts (e.g. expected key or provider types), surfacing as IllegalArgumentException.

Solutions

  1. Ensure the object is an instance of the required type (implement/extend it)
  2. Check obj.getClass() against the expected type before the call
  3. Verify you are not mixing incompatible library versions (e.g. old deprecated API types)
  4. If using reflection/factories, cast or validate the produced instance

Example fix

// before
Object key = loadKey(); // returns Object
Jwts.builder().signWith((Key) key); // may fail isInstanceOf
// after
Key key = loadKey();
if (!(key instanceof SecretKey)) { throw new IllegalArgumentException("need SecretKey"); }
Jwts.builder().signWith((SecretKey) key);
Defensive patterns

Strategy: type-guard

Validate before calling

if (obj == null || !requiredType.isInstance(obj)) {
    throw new IllegalArgumentException("Expected " + requiredType.getName()
        + ", got: " + (obj == null ? "null" : obj.getClass().getName()));
}

Type guard

if (!(obj instanceof SecretKey)) {
    throw new IllegalArgumentException("Key must be a SecretKey");
}
SecretKey key = (SecretKey) obj;

Try / catch

try {
    Assert.isInstanceOf(Key.class, obj, "Invalid key: ");
} catch (IllegalArgumentException e) {
    log.error("Type contract violated: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Passing an object of the wrong concrete type where a specific class is required, e.g. a custom Key implementation that isn't the expected interface/class, or a pluggable component (Serializer, Clock, compressor) of the wrong type handed to a builder or factory.

Common situations: Custom implementations after a library upgrade changed the expected interface; reflection-based instantiation returning a supertype; misconfigured plugins/factories returning the wrong class; mixing jjwt 0.11 and 0.12 API types on the classpath.

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


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/eed6eb69b347ef81. Report an issue: GitHub.

Appendix: source

Thrown at api/src/main/java/io/jsonwebtoken/lang/Assert.java:384

    /**
     * Assert that the provided object is an instance of the provided class.
     * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
     *
     * @param type    the type to check against
     * @param <T>     the object's expected type
     * @param obj     the object 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.
     * @return the non-null object IFF it is an instance of the specified {@code type}.
     * @throws IllegalArgumentException if the object is not an instance of clazz
     * @see Class#isInstance
     */
    public static <T> T isInstanceOf(Class<T> type, Object obj, String message) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            throw new IllegalArgumentException(message +
                    "Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
                    "] must be an instance of " + type);
        }
        return type.cast(obj);
    }

    /**
     * Asserts that the provided object is an instance of the provided class, throwing an
     * {@link IllegalStateException} otherwise.
     * <pre class="code">Assert.stateIsInstance(Foo.class, foo);</pre>
     *
     * @param type    the type to check against
     * @param <T>     the object's expected type
     * @param obj     the object 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.

View on GitHub (pinned to fb71496164)