google/gson · error · IndexOutOfBoundsException
Invalid time zone indicator '{}'
Error message
Invalid time zone indicator '{}' What it means
Thrown by ISO8601Utils when the character at the timezone position is neither 'Z' nor '+'/'-'. After the date/time portion is consumed, the parser inspects date.charAt(offset); any other character (e.g. a space, a letter, end-of-field noise) is rejected as an invalid timezone indicator.
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java:279
String act = timezone.getID();
if (!act.equals(timezoneId)) {
/* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given
* one without. If so, don't sweat.
* Yes, very inefficient. Hopefully not hit often.
* If it becomes a perf problem, add 'loose' comparison instead.
*/
String cleaned = act.replace(":", "");
if (!cleaned.equals(timezoneId)) {
throw new IndexOutOfBoundsException(
"Mismatching time zone indicator: "
+ timezoneId
+ " given, resolves to "
+ timezone.getID());
}
}
}
} else {
throw new IndexOutOfBoundsException(
"Invalid time zone indicator '" + timezoneIndicator + "'");
}
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);
return calendar.getTime();
// If we get a ParseException it'll already have the right message/offset.
// Other exception types can convert here.
} catch (IndexOutOfBoundsException | IllegalArgumentException e) {View on GitHub (pinned to 310ac341f2)
Solutions
- Fix the producer to emit ISO8601 (use 'Z' or numeric offset, no named zones).
- Pre-process the string: strip named zones and convert to an offset using a known mapping.
- Register a custom TypeAdapter<Date> that parses the actual format (e.g. 'EEE, dd MMM yyyy HH:mm:ss zzz' for RFC 1123).
- Validate the format with a regex at the boundary and reject/log non-ISO8601 inputs.
Example fix
// before
// JSON: {"at":"2020-01-01T12:00:00 UTC"} -> invalid indicator ' '
// after (producer fix): {"at":"2020-01-01T12:00:00Z"}
// or custom adapter for RFC 1123 strings:
Gson g = new GsonBuilder()
.registerTypeAdapter(Date.class, new TypeAdapter<Date>() {
private final DateFormat f = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
public Date read(JsonReader in) throws IOException {
try { return f.parse(in.nextString()); }
catch (ParseException e) { throw new JsonSyntaxException(e); }
}
public void write(JsonWriter out, Date v) throws IOException { out.value(f.format(v)); }
}).create(); Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern ISO =
Pattern.compile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$");
String raw = jsonNode.get("at").getAsString();
if (raw == null || !ISO.matcher(raw).matches()) {
throw new IllegalArgumentException("Not ISO8601 with Z/offset: " + raw);
} Try / catch
try {
return gson.fromJson(json, Event.class);
} catch (JsonSyntaxException e) {
if (e.getCause() instanceof ParseException
&& e.getCause().getMessage().contains("Invalid time zone indicator")) {
// input uses named zone or wrong format; switch adapter or reject
throw new IllegalArgumentException("Unsupported date format", e);
}
throw e;
} Prevention
- Reject named timezones ('UTC','EST') at ingestion; require numeric offsets.
- Validate date strings with an ISO8601 regex at the boundary.
- Use a custom TypeAdapter for any non-ISO format you must support.
- Document the exact date contract for producers.
When it happens
Trigger: Date string with a malformed trailing token: "2020-01-01T12:00:00 UTC" (space then letters), "2020-01-01T12:00:00X", or an unexpected separator. The parser expects exactly 'Z', '+', or '-' at that position.
Common situations: Human-readable timestamps with timezone names ("UTC", "EST"); RFC 1123 or RFC 822 date formats fed to a parser expecting ISO8601; copy-paste artifacts with trailing whitespace or newline; producers joining date and zone with a space.
Related errors
- Mismatching time zone indicator: {} given, resolves to {}
- No time zone indicator
- Invalid number: {}
- Failed parsing '{}' as SQL Date; at path {}
- Failed parsing '{}' as SQL Time; at path {}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/951a8a085edb5f82.
Report an issue: GitHub.