google/gson · error · IndexOutOfBoundsException
Invalid time zone indicator {timezoneIndicator}
Error message
Invalid time zone indicator {timezoneIndicator} What it means
Thrown internally by UtcDateTypeAdapter's parser when the character at the expected timezone position is not one of 'Z', '+', or '-'. The parser only accepts those three indicators; any other character (a letter, a digit, a space) is treated as an invalid indicator. This IndexOutOfBoundsException is caught and rethrown as a ParseException, then wrapped as JsonParseException by read().
Source
Thrown at extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java:204
}
}
}
// extract timezone
String timezoneId;
if (date.length() <= offset) {
throw new IllegalArgumentException("No time zone indicator");
}
char timezoneIndicator = date.charAt(offset);
if (timezoneIndicator == '+' || timezoneIndicator == '-') {
String timezoneOffset = date.substring(offset);
timezoneId = GMT_ID + timezoneOffset;
offset += timezoneOffset.length();
} else if (timezoneIndicator == 'Z') {
timezoneId = GMT_ID;
offset += 1;
} else {
throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator);
}
TimeZone timezone = TimeZone.getTimeZone(timezoneId);
if (!timezone.getID().equals(timezoneId)) {
throw new IndexOutOfBoundsException();
}
Calendar calendar = new GregorianCalendar(timezone);
calendar.setLenient(false);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);
calendar.set(Calendar.MILLISECOND, milliseconds);
pos.setIndex(offset);View on GitHub (pinned to 8b8628c656)
Solutions
- Convert named/offset zones to the supported form: replace "UTC"/"GMT" with "Z", replace "PST" with "-08:00", etc., before parsing.
- Use a lenient SimpleDateFormat or java.time parser that accepts zone names if you must consume such input, instead of UtcDateTypeAdapter.
- Sanitize the input string with a regex/replace step that normalizes the trailing timezone token.
- Validate the format against ^.*[Z+-]$ at the timezone position before handing off.
Example fix
// before String json = "\"2024-01-01T12:00:00 UTC\""; Date d = gson.fromJson(json, Date.class); // throws: ' ' is invalid indicator // after String json = "\"2024-01-01T12:00:00Z\""; Date d = gson.fromJson(json, Date.class);
Defensive patterns
Strategy: validation
Validate before calling
// Normalize named zones to offset form before parsing
static String normalizeZone(String date) {
date = date.replaceAll("(?i)\\s*(UTC|GMT)$", "Z");
// Map common named zones to offsets (extend as needed)
date = date.replaceAll("(?i)\\sPST$", "-08:00");
date = date.replaceAll("(?i)\\sPDT$", "-07:00");
if (!date.matches(".*[Zz]$|.*/[+-]\\d{2}:?\\d{2}$")) {
throw new IllegalArgumentException("Unrecognized timezone in: " + date);
}
return date;
} Type guard
static boolean hasValidTimezoneIndicator(String date) {
if (date == null || date.isEmpty()) return false;
char c = date.charAt(date.length() - 1);
return c == 'Z' || c == 'z' || date.matches(".*[+-]\\d{2}:?\\d{2}$");
} Try / catch
try {
Date d = gson.fromJson(json, Date.class);
} catch (JsonParseException e) {
Throwable c = e.getCause();
if (c != null && c.getMessage() != null && c.getMessage().contains("Invalid time zone indicator")) {
// normalize the zone token and retry, or reject the payload
} else throw e;
} Prevention
- Standardize producer output to strict ISO-8601 with Z or numeric offset only.
- Map named timezones to offsets before parsing if you cannot change the producer.
- Reject payloads with named-zone tokens at a validation boundary.
- Consider java.time with a ZoneRulesProvider-based parser for named-zone support.
When it happens
Trigger: Date strings like "2024-01-01T12:00:00X", "2024-01-01T12:00:00 UTC", or "2024-01-01T12:00:00GMT" where a non-standard token sits at the timezone slot; corrupted or hand-edited timestamps; locale-specific formats that spell out the zone.
Common situations: Third-party APIs returning non-strict ISO-8601 (named zones like "PST", "EST", "UTC" spelled out); legacy systems emitting "GMT" literally; encoding issues inserting stray characters; copy-paste errors.
Related errors
- No time zone indicator
- Failed to parse date [{input}]: {fail.getMessage()}
- {value}
- Invalid number: {value}
- Array must have size 1, but has size {size}
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/533b15b0e12889ad.json.
Report an issue: GitHub.