google/gson · error · JsonSyntaxException

Missing field; at path

Error message

Missing ${fieldName} field; at path ${path}

What it means

Composite java.time adapters (LocalDateTime, OffsetDateTime, OffsetTime, ZonedDateTime) call requireNonNullField for each mandatory sub-component; if a required member ('date', 'time', 'dateTime', 'offset', or 'zone') is absent in the JSON object, this JsonSyntaxException is thrown naming the missing field.

Solutions

  1. Make the producer emit all required sub-objects (even when null, emit proper null/empty objects).
  2. Register a custom TypeAdapter for the java.time type that tolerates missing fields with sensible defaults.
  3. Pre-validate the JSON object's keys before deserialization.
  4. If migrating formats, serialize then re-deserialize with the same Gson to confirm round-trip compatibility.

Example fix

// before: {"time":{"hour":10}}
Gson().fromJson(json, LocalDateTime::class.java) // Missing date field

// after: include all required sub-objects
{"date":{"year":2024,"month":1,"day":15},"time":{"hour":10,"minute":0,"second":0,"nano":0}}
Defensive patterns

Strategy: validation

Validate before calling

// Validate required sub-fields for java.time composite types
static boolean hasAll(String json, String... fields) {
  JsonObject o = JsonParser.parseString(json).getAsJsonObject();
  for (String f : fields) if (!o.has(f)) return false;
  return true;
}
// e.g. LocalDateTime needs 'date' and 'time'
if (!hasAll(json, "date", "time")) reject();

Try / catch

try {
  gson.fromJson(json, LocalDateTime.class);
} catch (JsonSyntaxException e) {
  if (e.getMessage().startsWith("Missing ") && e.getMessage().contains("field")) {
    // missing sub-object; default it or reject upstream
    log.warn("Incomplete java.time payload: {}", e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing LocalDateTime from {"time":{...}} (missing 'date'), OffsetDateTime missing 'dateTime' or 'offset', OffsetTime missing 'time'/'offset', or ZonedDateTime missing any of 'dateTime'/'offset'/'zone'.

Common situations: Partial payloads from producers that omit null sub-objects; renaming fields on the producer side; schema drift after a Gson or JDK upgrade that changed the encoding.

Related errors


AI-assisted analysis of google/gson@310ac341f2 (2026-08-10). Data as JSON: /api/errors/521e2cebf085f679. Report an issue: GitHub.

Appendix: source

Thrown at gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java:444

          } else if (rawType == ZoneId.class || rawType == ZoneOffset.class) {
            // We don't check ZoneId.class.isAssignableFrom(rawType) because we don't want to match
            // the non-public class ZoneRegion in the runtime type check in
            // TypeAdapterRuntimeTypeWrapper.write. If we did, then our ZONE_ID would take
            // precedence over a ZoneId adapter that the user might have registered. (This exact
            // situation showed up in a Google-internal test.)
            adapter = ZONE_ID;
          } else if (rawType == ZonedDateTime.class) {
            adapter = zonedDateTime(gson);
          }
          @SuppressWarnings("unchecked")
          TypeAdapter<T> result = (TypeAdapter<T>) adapter;
          return result;
        }
      };

  private static <T> T requireNonNullField(T field, String fieldName, JsonReader reader) {
    if (field == null) {
      throw new JsonSyntaxException(
          "Missing " + fieldName + " field; at path " + reader.getPreviousPath());
    }
    return field;
  }
}

View on GitHub (pinned to 310ac341f2)