google/gson · error · IllegalArgumentException
No time zone indicator
Error message
No time zone indicator
What it means
Thrown internally by UtcDateTypeAdapter's ISO-8601 parser when the date string has no characters left at the position where a time-zone indicator ('Z', '+', or '-') is expected. The adapter requires every parsed date to carry an explicit timezone; a bare date like "2024-01-01T00:00:00" without a zone is rejected. This IllegalArgumentException is caught and converted into a ParseException, which read() then wraps as a JsonParseException.
Source
Thrown at extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java:193
offset += 1;
}
// second and milliseconds can be optional
if (date.length() > offset) {
char c = date.charAt(offset);
if (c != 'Z' && c != '+' && c != '-') {
seconds = parseInt(date, offset, offset += 2);
// milliseconds can be optional in the format
if (checkOffset(date, offset, '.')) {
milliseconds = parseInt(date, offset += 1, offset += 3);
}
}
}
}
// 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();
}
View on GitHub (pinned to 8b8628c656)
Solutions
- Ensure the date string includes an explicit timezone: append 'Z' for UTC or '+HH:mm'/'-HH:mm' for an offset (e.g. "2024-01-01T12:00:00Z").
- Normalize date strings on the producer to always emit a timezone before sending.
- If you cannot change the input, register a custom TypeAdapter<Date> that defaults omitted zones to UTC instead of using UtcDateTypeAdapter.
- Pre-validate the string with a regex like .*[ZzZ+-]\d\d:?\d\d$ before parsing.
Example fix
// before String json = "\"2024-01-01T12:00:00\""; // no timezone indicator Date d = gson.fromJson(json, Date.class); // throws (via JsonParseException) // after String json = "\"2024-01-01T12:00:00Z\""; Date d = gson.fromJson(json, Date.class);
Defensive patterns
Strategy: validation
Validate before calling
// Validate the date string has a timezone indicator before parsing
static void requireTimezone(String date) {
// last meaningful char must be Z, +, or -; or end with offset like +HH:mm
if (!date.matches(".*[Zz]$|.*/[+-]\\d{2}:?\\d{2}$")) {
throw new IllegalArgumentException("Date missing timezone: " + date);
}
} Type guard
static boolean hasTimezoneIndicator(String date) {
if (date == null || date.isEmpty()) return false;
char last = date.charAt(date.length() - 1);
if (last == 'Z' || last == 'z') return true;
// tolerate trailing offset +HH:mm / -HH:mm
return 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("No time zone indicator")) {
// retry after appending 'Z' if UTC was intended, or reject
} else throw e;
} Prevention
- Always emit explicit timezones (UTC 'Z' or an offset) on the producer side.
- Pre-validate incoming date strings with a regex before parsing.
- If input legitimately omits the zone, register a custom Date adapter that defaults to UTC.
- Prefer java.time Instant/OffsetDateTime in APIs to make the zone requirement explicit.
When it happens
Trigger: Parsing a date string that ends right after the time component with no zone, e.g. "2024-01-01T12:00:00"; a date-only string "20240101" where the optional time section is absent and nothing follows; truncated input. Surfaced to the Gson caller as JsonParseException during fromJson when the UtcDateTypeAdapter is registered.
Common situations: Backend sends ISO-8601 without timezone (assumed local/UTC implicitly); mixing date formats where some payloads omit the zone; data from systems that produce "local" timestamps; trimming trailing characters during transport.
Related errors
- Invalid time zone indicator {timezoneIndicator}
- 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/749d35c36a0d474b.json.
Report an issue: GitHub.