jwtk/jjwt · error · ClassCastException

Cannot cast ${value.getClass().getName()} to ${COLLECTION_TY

Error message

Cannot cast ${value.getClass().getName()} to ${COLLECTION_TYPE.getName()}<${IDIOMATIC_TYPE.getName()}>: At least one element is not an instance of ${IDIOMATIC_TYPE.getName()}

What it means

DefaultParameter.cast, after confirming the value is the expected collection type, checks that its elements are instances of the declared element type (IDIOMATIC_TYPE). If at least one element is of the wrong type, a ClassCastException is thrown noting 'At least one element is not an instance of ...'. This only inspects the first element, so it detects a bad first element specifically.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/DefaultParameter.java:83

    @SuppressWarnings("unchecked")
    @Override
    public T cast(Object value) {
        if (value != null) {
            if (COLLECTION_TYPE != null) { // parameter represents a collection, ensure it and its elements are the expected type:
                if (!COLLECTION_TYPE.isInstance(value)) {
                    String msg = "Cannot cast " + value.getClass().getName() + " to " +
                            COLLECTION_TYPE.getName() + "<" + IDIOMATIC_TYPE.getName() + ">";
                    throw new ClassCastException(msg);
                }
                Collection<?> c = COLLECTION_TYPE.cast(value);
                if (!c.isEmpty()) {
                    Object element = c.iterator().next();
                    if (!IDIOMATIC_TYPE.isInstance(element)) {
                        String msg = "Cannot cast " + value.getClass().getName() + " to " +
                                COLLECTION_TYPE.getName() + "<" + IDIOMATIC_TYPE.getName() + ">: At least one " +
                                "element is not an instance of " + IDIOMATIC_TYPE.getName();
                        throw new ClassCastException(msg);
                    }
                }
            } else if (!IDIOMATIC_TYPE.isInstance(value)) {
                String msg = "Cannot cast " + value.getClass().getName() + " to " + IDIOMATIC_TYPE.getName();
                throw new ClassCastException(msg);
            }
        }
        return (T) value;
    }

    @Override
    public boolean isSecret() {
        return SECRET;
    }

    @Override
    public int hashCode() {
        return this.ID.hashCode();

View on GitHub (pinned to fb71496164)

Solutions

  1. Ensure every element matches the declared element type before assignment.
  2. Convert elements explicitly (map each to String/Long as required) before setting the claim.
  3. If the JWT payload genuinely contains mixed types, change the registered parameter element type to a common supertype (e.g. Object).

Example fix

// before
List<Object> roles = Arrays.asList("admin", 42);
jwt.claim("roles", roles);
// after
List<String> roles = Arrays.asList("admin", "42");
jwt.claim("roles", roles);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean ok = value instanceof Collection
    && ((Collection<?>) value).stream().allMatch(expectedElemType::isInstance);
if (!ok) { /* convert or reject */ }

Type guard

static <T> boolean allInstanceOf(Collection<?> c, Class<T> t) {
    return c.stream().allMatch(t::isInstance);
}

Try / catch

try {
    param.cast(collection);
} catch (ClassCastException e) {
    // inspect elements, convert or reject the collection
}

Prevention

When it happens

Trigger: Assigning a Collection whose first element is not of the declared element type, e.g. a List<Object> containing an Integer into a Collection<String> parameter, or a deserialized heterogeneous JSON array.

Common situations: JSON arrays with mixed types (["a", 1]); generics erasure letting List<Integer> slip into a List<String> slot; builders taking raw Collection types.

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/f9ec44e2e92d58f9. Report an issue: GitHub.