google/gson · error · NumberFormatException

Invalid number: {value}

Error message

Invalid number: {value}

What it means

Thrown internally by UtcDateTypeAdapter.parseInt() when the FIRST character of the integer field being parsed is not a decimal digit (Character.digit returns < 0). This means a non-numeric character appears where the parser expects the start of a number (e.g. a letter where the year should be). It is a NumberFormatException that flows up into the umbrella ParseException (error 7).

Source

Thrown at extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java:267

   * @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);
      }
      result = -digit;
    }
    while (i < endIndex) {
      digit = Character.digit(value.charAt(i++), 10);
      if (digit < 0) {
        throw new NumberFormatException("Invalid number: " + value);
      }
      result *= 10;
      result -= digit;
    }
    return -result;
  }
}

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Ensure all numeric date fields (year, month, day, hour, minute, second, ms) contain only decimal digits in fixed widths.
  2. Pre-validate with a regex that pins digit positions, e.g. ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*.
  3. Use java.time with a DateTimeFormatter whose pattern matches the actual input (e.g. MMM for month names) via a custom adapter.
  4. Sanitize/normalize the input at the source.

Example fix

// before: non-digit in numeric position
String json = "\"YYYY-01-01T00:00:00Z\"";
Date d = gson.fromJson(json, Date.class); // JsonParseException via NumberFormatException

// after: numeric fields
String json = "\"2024-01-01T00:00:00Z\"";
Date d = gson.fromJson(json, Date.class);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure numeric date fields contain only digits at the right positions
static boolean digitsOnlyAt(String date, int start, int end) {
  if (date.length() < end) return false;
  for (int i = start; i < end; i++) {
    if (!Character.isDigit(date.charAt(i))) return false;
  }
  return true;
}
static boolean validIsoNumbers(String d) {
  return digitsOnlyAt(d, 0, 4) && digitsOnlyAt(d, 5, 7) && digitsOnlyAt(d, 8, 10);
}

Type guard

static boolean startsWithDigit(String date) {
  return date != null && !date.isEmpty() && Character.isDigit(date.charAt(0));
}

Try / catch

try {
  Date d = gson.fromJson(json, Date.class);
} catch (JsonParseException e) {
  if (e.getCause() != null && e.getCause().getCause() instanceof NumberFormatException) {
    // non-digit in numeric position; sanitize or reject
  } else throw e;
}

Prevention

When it happens

Trigger: Date strings like "abcd-01-01T00:00:00Z" where the year contains letters; separators appearing where digits are expected; locale-specific month names; corrupted numeric fields.

Common situations: Garbled payloads; dates formatted with month names ("Jan") instead of numeric months; data-entry or transport corruption introducing non-digits; wrong field ordering.

Related errors


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