google/gson · error · NumberFormatException

value

Error message

value

What it means

ISO8601Utils.parseInt throws NumberFormatException(value) when its beginIndex/endIndex arguments fall outside the string bounds or are inverted (beginIndex<0, endIndex>length, or beginIndex>endIndex). This typically means the date string was truncated so that an expected numeric field could not be read at the computed offset.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java:335

   * @return true if the expected character exist at the given offset
   */
  private static boolean checkOffset(String value, int offset, char expected) {
    return (offset < value.length()) && (value.charAt(offset) == expected);
  }

  /**
   * Parse an integer located between 2 given offsets in a string
   *
   * @param value the string to parse
   * @param beginIndex the start index for the integer in the string
   * @param endIndex the end index for the integer in the string
   * @return the int
   * @throws NumberFormatException if the value is not a number
   */
  private static int parseInt(String value, int beginIndex, int endIndex)
      throws NumberFormatException {
    if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {
      throw new NumberFormatException(value);
    }
    // use same logic as in Integer.parseInt() but less generic we're not supporting negative values
    int i = beginIndex;
    int result = 0;
    int digit;
    if (i < endIndex) {
      digit = Character.digit(value.charAt(i++), 10);
      if (digit < 0) {
        throw new NumberFormatException("Invalid number: " + value.substring(beginIndex, endIndex));
      }
      result = -digit;
    }
    while (i < endIndex) {
      digit = Character.digit(value.charAt(i++), 10);
      if (digit < 0) {
        throw new NumberFormatException("Invalid number: " + value.substring(beginIndex, endIndex));
      }
      result *= 10;

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Ensure the source string has all required components (date and time).
  2. Pre-validate the length/format against the expected ISO-8601 shape.
  3. Register a custom adapter tolerant of missing components (defaulting time to 00:00:00).

Example fix

// before
Date d = gson.fromJson("\"2024-01\"", Date.class);

// after
String s = json.length() == 7 ? json + "-01T00:00:00Z" : json;
Date d = gson.fromJson('"' + s + '"', Date.class);
Defensive patterns

Strategy: validation

Validate before calling

boolean isCompleteIso8601(String iso) {
  // expect at least yyyy-MM-ddTHH:mm:ss plus timezone
  return iso != null && iso.length() >= 20 && iso.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.*");
}

Type guard

static boolean hasMinimumDateLength(String iso) { return iso != null && iso.length() >= 20; }

Try / catch

try {
  Date d = gson.fromJson(json, Date.class);
} catch (JsonSyntaxException e) {
  // treat truncated date as null/epoch or reject
}

Prevention

When it happens

Trigger: Parsing a date string that is too short for the expected structure, e.g. '2024-01' when a full date-time was expected, so parseInt runs off the end.

Common situations: Truncated payloads, partial field updates, or a producer that emits date-only where date-time is expected.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/e0f124f343526b33.json. Report an issue: GitHub.