FasterXML/jackson-databind · error · IllegalArgumentException

Failed to parse Date value '%s': %s

Error message

Failed to parse Date value '%s': %s

What it means

DeserializationContext.parseDate() tries to parse a string into a java.util.Date using the currently configured DateFormat (the mapper's date format or the default ISO-8601 format). When DateFormat.parse() throws a ParseException, Jackson rethrows it as an IllegalArgumentException with both the offending value and the underlying parse message. This is the core failure for date/calendar deserialization when the input doesn't match the expected pattern.

Source

Thrown at src/main/java/tools/jackson/databind/DeserializationContext.java:1185

     */

    /**
     * Convenience method for parsing a Date from given String, using
     * currently configured date format (accessed using
     * {@link DeserializationConfig#getDateFormat()}).
     *<p>
     * Implementation will handle thread-safety issues related to
     * date formats such that first time this method is called,
     * date format is cloned, and cloned instance will be retained
     * for use during this deserialization round.
     */
    public Date parseDate(String dateStr) throws IllegalArgumentException
    {
        try {
            DateFormat df = _getDateFormat();
            return df.parse(dateStr);
        } catch (ParseException e) {
            throw new IllegalArgumentException("Failed to parse Date value '%s': %s".formatted(dateStr,
                    ClassUtil.exceptionMessage(e)));
        }
    }

    /**
     * Convenience method for constructing Calendar instance set
     * to specified time, to be modified and used by caller.
     */
    public Calendar constructCalendar(Date d) {
        // 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed.
        Calendar c = Calendar.getInstance(getTimeZone());
        c.setTime(d);
        return c;
    }

    /*
    /**********************************************************************
    /* Extension points for more esoteric data coercion

View on GitHub (pinned to a50c7d2a1d)

Solutions

  1. Set a matching date format on the mapper or field: mapper.setDateFormat(new SimpleDateFormat("MM/dd/yyyy")) or @JsonFormat(shape=STRING, pattern="MM/dd/yyyy").
  2. Validate/sanitize incoming date strings upstream so only the expected pattern reaches Jackson.
  3. Enable lenient parsing: ((SimpleDateFormat)fmt).setLenient(true) on the configured format.
  4. Use a custom ValueDeserializer for Date that tries multiple patterns, or switch the field to java.time.LocalDate/Instant with ACCEPT_CASE_INSENSITIVE_VALUES / custom adapters.
  5. Enable DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE and verify the input includes/excludes timezone as the pattern expects.

Example fix

// before
ObjectMapper m = new ObjectMapper(); // default ISO format
Date d = m.readValue("\"01/14/2024\"", Date.class); // fails
// after
SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
JsonMapper m = JsonMapper.builder().defaultDateFormat(f).build();
Date d = m.readValue("\"01/14/2024\"", Date.class);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate a date string against the configured format before parse
static boolean isParsable(DateFormat fmt, String s) {
    try { synchronized (fmt) { fmt.parse(s); } return true; }
    catch (ParseException e) { return false; }
}

Type guard

// No compile-time type guard for runtime string parsing; rely on validation.

Try / catch

try {
    return mapper.readValue(json, Date.class);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Failed to parse Date value")) {
        // fall back: store raw string or use a default date
    }
    throw e;
}

Prevention

When it happens

Trigger: Deserializing a date field whose string value doesn't match the configured date format (e.g. '2024/01/01' against an ISO format, or 'Jan 1st' against 'yyyy-MM-dd'); no custom date format set and the input is non-ISO; locale/timezone mismatch causing the parser to reject a value; a numeric timestamp string where a formatted date was expected (or vice versa).

Common situations: Default Jackson expects ISO-8601 ('yyyy-MM-dd'T'HH:mm:ss.SSSX') but the API/DB returns 'MM/dd/yyyy'; timezone differences between server and client producing unparseable offsets; mixing java.util.Date with java.time types after a partial migration; CSV/legacy feeds with inconsistent date shapes; a JsonFormat annotation with a pattern that doesn't cover all incoming values.

Understand the failure class

Related errors


AI-assisted analysis of FasterXML/jackson-databind@a50c7d2a1d (2026-08-06). Data as JSON: /api/errors/141426c388a70dfe. Report an issue: GitHub.