jwtk/jjwt · error · IllegalArgumentException

Cannot create Date from object of type ${v.getClass().getNam

Error message

Cannot create Date from object of type ${v.getClass().getName()}.

What it means

JwtDateConverter.toDate converts a JWT date claim value (exp, nbf, iat) into a java.util.Date. It accepts Number (epoch seconds/millis) and ISO-8601 String inputs; any other type throws IllegalArgumentException 'Cannot create Date from object of type ...'.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/JwtDateConverter.java:91

     * @param v the object value to represent as a Date.
     * @return a {@link Date} equivalent of the specified object value using heuristics.
     */
    public static Date toDate(Object v) {
        if (v == null) {
            return null;
        } else if (v instanceof Date) {
            return (Date) v;
        } else if (v instanceof Calendar) { //since 0.10.0
            return ((Calendar) v).getTime();
        } else if (v instanceof Number) {
            //assume millis:
            long millis = ((Number) v).longValue();
            return new Date(millis);
        } else if (v instanceof String) {
            return parseIso8601Date((String) v); //ISO-8601 parsing since 0.10.0
        } else {
            String msg = "Cannot create Date from object of type " + v.getClass().getName() + ".";
            throw new IllegalArgumentException(msg);
        }
    }

    /**
     * Parses the specified ISO-8601-formatted string and returns the corresponding {@link Date} instance.
     *
     * @param value an ISO-8601-formatted string.
     * @return a {@link Date} instance reflecting the specified ISO-8601-formatted string.
     * @since 0.10.0
     */
    private static Date parseIso8601Date(String value) throws IllegalArgumentException {
        try {
            return DateFormats.parseIso8601Date(value);
        } catch (ParseException e) {
            String msg = "String value is not a JWT NumericDate, nor is it ISO-8601-formatted. " +
                    "All heuristics exhausted. Cause: " + e.getMessage();
            throw new IllegalArgumentException(msg, e);
        }

View on GitHub (pinned to fb71496164)

Solutions

  1. Pass epoch-millis Number (new Date().getTime()) or an ISO-8601 String for date claims.
  2. Inspect the raw JSON of the token to see the claim's actual type and fix the producer.
  3. Pre-validate with instanceof Number/String before passing to the converter, converting or rejecting other types.

Example fix

// before
jwt.claim("exp", someCustomDateObject); // unsupported type
// after
jwt.claim("exp", System.currentTimeMillis() / 1000L); // epoch seconds as Number
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(v instanceof Number) && !(v instanceof String)) {
    throw new IllegalArgumentException("Date claim must be epoch number or ISO-8601 string: " + v);
}

Type guard

static Date toDate(Object v) {
    if (v instanceof Number) return new Date(((Number) v).longValue());
    if (v instanceof String) return Date.from(Instant.parse((String) v));
    return null;
}

Try / catch

try {
    Date d = (Date) claims.get("exp");
} catch (IllegalArgumentException | ClassCastException e) {
    // parse claim manually or reject the token
}

Prevention

When it happens

Trigger: A date claim deserialized as something other than Number or String - e.g. a Map/List from malformed JSON, a Boolean, or a custom object set programmatically into a claim typed as a date.

Common situations: Custom JSON deserializers producing non-standard types; manually building claims with wrong types (new Object()); third-party token issuers emitting dates in exotic formats parsed into containers.

Related errors


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