{"record":{"id":"668e8780f49fc047","repo":"google/gson","slug":"failed-to-parse-date-input-fail-getmessage","errorCode":null,"errorMessage":"Failed to parse date [${input}]: ${fail.getMessage()}","messagePattern":"Failed to parse date \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java","lineNumber":230,"sourceCode":"      Calendar calendar = new GregorianCalendar(timezone);\n      calendar.setLenient(false);\n      calendar.set(Calendar.YEAR, year);\n      calendar.set(Calendar.MONTH, month - 1);\n      calendar.set(Calendar.DAY_OF_MONTH, day);\n      calendar.set(Calendar.HOUR_OF_DAY, hour);\n      calendar.set(Calendar.MINUTE, minutes);\n      calendar.set(Calendar.SECOND, seconds);\n      calendar.set(Calendar.MILLISECOND, milliseconds);\n\n      pos.setIndex(offset);\n      return calendar.getTime();\n      // If we get a ParseException it'll already have the right message/offset.\n      // Other exception types can convert here.\n    } catch (IndexOutOfBoundsException | IllegalArgumentException e) {\n      fail = e;\n    }\n    String input = (date == null) ? null : (\"'\" + date + \"'\");\n    throw new ParseException(\n        \"Failed to parse date [\" + input + \"]: \" + fail.getMessage(), pos.getIndex());\n  }\n\n  /**\n   * Check if the expected character exist at the given offset in the value.\n   *\n   * @param value the string to check at the specified offset\n   * @param offset the offset to look for the expected character\n   * @param expected the expected character\n   * @return true if the expected character exist at the given offset\n   */\n  private static boolean checkOffset(String value, int offset, char expected) {\n    return (offset < value.length()) && (value.charAt(offset) == expected);\n  }\n\n  /**\n   * Parse an integer located between 2 given offsets in a string\n   *","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java#L212-L248","documentation":"Thrown by UtcDateTypeAdapter when an ISO-8601 date string cannot be parsed. The adapter ported Jackson's ISO8601Utils parser; if any extraction step throws IndexOutOfBoundsException or IllegalArgumentException (truncated digits, missing timezone indicator, invalid chars), it captures that cause and rethrows a ParseException whose message embeds the offending input and the underlying reason. The read() method wraps this ParseException into a JsonParseException.","triggerScenarios":"Date string not in ISO-8601 form (e.g. \"01/02/2020\", epoch millis, \"Mar 5, 2021\"); string too short for the year/month/day digits; missing or invalid timezone indicator (not 'Z', '+', or '-'); non-numeric characters where digits expected; null handled separately but malformed values reach parse().","commonSituations":"Mixing date formats between producer and consumer; backend sending locale-specific formats; receiving epoch numbers as strings; trimming bugs that drop the timezone; APIs that emit RFC1123 or custom formats instead of ISO-8601.","solutions":["Send dates as strict ISO-8601: yyyy-MM-dd'T'HH:mm:ss[.sss][Z|+HH:mm], e.g. \"2024-05-01T12:30:00Z\".","If your input uses a different format, register a custom TypeAdapter<Date> built from a matching SimpleDateFormat instead of UtcDateTypeAdapter.","Pre-validate the string with a regex / DateTimeFormatter.parse() before deserialization to give a clearer error.","Log the exact input value from the message to identify the offending producer."],"exampleFix":"// before: input \"2020-13-40\" -> throws\nString json = \"\\\"2020-13-40\\\"\";\n\n// after: valid ISO-8601 UTC\nString json = \"\\\"2020-05-01T12:30:00Z\\\"\";","handlingStrategy":"try-catch","validationCode":"// Pre-validate ISO-8601 before deserialization\nstatic boolean isIso8601(String s) {\n  return s != null && s.matches(\"\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}(\\\\.\\\\d+)?(Z|[+-]\\\\d{2}:?\\\\d{2})\");\n}\nif (!isIso8601(dateStr)) throw new IllegalArgumentException(\"Bad date: \" + dateStr);","typeGuard":null,"tryCatchPattern":"try { gson.fromJson(json, Date.class); }\ncatch (JsonParseException e) {\n  Throwable c = e.getCause();\n  if (c instanceof ParseException && c.getMessage().startsWith(\"Failed to parse date\")) {\n    // log offending value, apply fallback parsing or reject\n  } else throw e;\n}","preventionTips":["Standardize on ISO-8601 UTC across producers and consumers.","If formats differ, register a custom TypeAdapter<Date> using the matching SimpleDateFormat.","Capture and log the exact input value to diagnose the producer."],"tags":["date","utc-date-adapter","deserialization","iso8601","gson-extras"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}