google/gson · error · JsonSyntaxException
Failed parsing ' ' as Date; at path
Error message
Failed parsing '${s}' as Date; at path ${path} What it means
DefaultDateTypeAdapter tries every configured DateFormat, then falls back to ISO8601Utils.parse; if all attempts throw ParseException it wraps the final failure in a JsonSyntaxException naming the offending string and JSON path. This is the catch-all 'I could not interpret this token as a Date' error.
Solutions
- Set the matching pattern via GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssX").create().
- Register a custom TypeAdapter<Date> that parses the exact incoming format.
- If the producer can change, emit ISO8601 (e.g. java.time.Instant toString).
- Coerce epoch-millis numbers to Date with a custom deserializer rather than relying on string parsing.
Example fix
// before
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd").create()
gson.fromJson("\"2024-01-15T10:30:00Z\"", Date::class.java) // fails
// after: match the actual input format
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssX").create()
gson.fromJson("\"2024-01-15T10:30:00Z\"", Date::class.java) Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-parse and validate the date with the configured format
static boolean matchesFormat(String s, String pattern) {
try { new SimpleDateFormat(pattern, Locale.US).parse(s); return true; }
catch (ParseException e) { return false; }
}
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssX").create(); Try / catch
try {
gson.fromJson(json, DateHolder.class);
} catch (JsonSyntaxException e) {
if (e.getMessage().startsWith("Failed parsing ")) {
// date format mismatch: adjust setDateFormat or coerce input
log.warn("Unparseable date: {}", e.getMessage());
}
throw e;
} Prevention
- Set an explicit date format on GsonBuilder matching your producer.
- Prefer ISO8601 on both ends.
- Register a custom Date TypeAdapter for non-standard inputs.
- Avoid relying on JVM default locale date formats; they vary.
When it happens
Trigger: Deserializing a JSON string into a java.util.Date (or Date subclass) where the string matches neither the GsonBuilder.setDateFormat pattern(s) nor any ISO8601 variant. Example: format set to 'yyyy-MM-dd' but JSON contains '01/15/2024'.
Common situations: Switching GsonBuilder date format after data was produced; locale-sensitive default formats differing between JVMs; consuming an external API whose date format (e.g. epoch millis as number, RFC-1123) Gson doesn't try; mixing SimpleDateFormat instances across threads.
Related errors
- Failed parsing ' ' as BigDecimal; at path
- Failed to parse date
- Array must have size 1, but has size
- Attempted to deserialize a java.lang.Class. Forgot to…
- Cannot allocate . Usage of JDK sun.misc.Unsafe is enabled…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/97f4496c51b13ba9.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java:184
String s = in.nextString();
// Needs to be synchronized since JDK DateFormat classes are not thread-safe
synchronized (dateFormats) {
for (DateFormat dateFormat : dateFormats) {
TimeZone originalTimeZone = dateFormat.getTimeZone();
try {
return dateFormat.parse(s);
} catch (ParseException ignored) {
// OK: try the next format
} finally {
dateFormat.setTimeZone(originalTimeZone);
}
}
}
try {
return ISO8601Utils.parse(s, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(
"Failed parsing '" + s + "' as Date; at path " + in.getPreviousPath(), e);
}
}
@Override
public String toString() {
DateFormat defaultFormat = dateFormats.get(0);
if (defaultFormat instanceof SimpleDateFormat) {
return SIMPLE_NAME + '(' + ((SimpleDateFormat) defaultFormat).toPattern() + ')';
} else {
return SIMPLE_NAME + '(' + defaultFormat.getClass().getSimpleName() + ')';
}
}
}
View on GitHub (pinned to 310ac341f2)