google/gson · error · NumberFormatException
Invalid number: " + value.substring(beginIndex, endIndex)
Error message
Invalid number: " + value.substring(beginIndex, endIndex)
What it means
ISO8601Utils.parseInt reports 'Invalid number' when the first character of an expected numeric field is not a digit (Character.digit returns < 0). This means a non-numeric character appears at the start of a year/month/day/hour/minute/second slot in the ISO-8601 string.
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java:344
* @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;
result -= digit;
}
return -result;
}
/**
* Zero pad a number to a specified length
*
* @param buffer buffer to use for paddingView on GitHub (pinned to 8b8628c656)
Solutions
- Correct the source string so each numeric field begins with a digit.
- Pre-validate the format with an ISO-8601 regex before parsing.
- Register a custom date adapter with a lenient parser and logging.
Example fix
// before
Date d = gson.fromJson("\"20X4-01-01T00:00:00Z\"", Date.class);
// after
if (!source.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) throw new IllegalArgumentException("bad date");
Date d = gson.fromJson('"' + source + '"', Date.class); Defensive patterns
Strategy: validation
Validate before calling
boolean isoDigitsAt(String iso, int start, int len) {
if (iso == null || start + len > iso.length()) return false;
for (int i = 0; i < len; i++) if (!Character.isDigit(iso.charAt(start + i))) return false;
return true;
} Type guard
static boolean firstFieldStartsWithDigit(String iso) {
return iso != null && !iso.isEmpty() && Character.isDigit(iso.charAt(0));
} Try / catch
try {
Date d = gson.fromJson(json, Date.class);
} catch (JsonSyntaxException e) {
// reject malformed date, log for producer follow-up
} Prevention
- Validate ISO-8601 against a strict regex before parsing.
- Reject unexpected characters at known offsets.
- Use java.time DateTimeFormatter with strictResolverStyle.
When it happens
Trigger: A date string where a numeric component begins with a non-digit, e.g. '20X4-01-01' for the year, or a separator appears too early.
Common situations: Corrupted/tampered strings, encoding artifacts, or a producer that inserts a literal where a digit was expected.
Related errors
- No time zone indicator
- Mismatching time zone indicator: " + timezoneId + " given, r
- Invalid time zone indicator '" + timezoneIndicator + "'
- value
- Failed parsing '" + s + "' as SQL Date; at path " + in.getPr
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/73a9248482ccae78.json.
Report an issue: GitHub.