google/gson · error · JsonSyntaxException

Missing {fieldName} field; at path {path}

Error message

Missing {fieldName} field; at path {path}

What it means

Thrown by JavaTimeTypeAdapters.requireNonNullField when a required subfield {fieldName} is absent while deserializing a composite java.time type. The composite adapters (LocalDateTime, OffsetDateTime, OffsetTime, ZonedDateTime) build the value from named sub-objects; if one of date/time/dateTime/offset/zone is missing the build cannot proceed. The {path} is the reader's previous path.

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 8b8628c656)

Solutions

  1. Make the producer emit all required subfields with the exact keys Gson expects (date/time for LocalDateTime; dateTime/offset for OffsetDateTime; dateTime/offset/zone for ZonedDateTime).
  2. Register a custom TypeAdapter for the java.time type that maps the producer's actual key names.
  3. If the value can legitimately be missing, model the field as nullable and have the producer send JSON null.
  4. Pre-scan the JSON object for the required keys and report a data-contract error to the producer.

Example fix

// before: '{"time":{"hour":10}}'  -> Missing date field
// after: include all required sub-objects
String json = "{\"date\":{\"year\":2025,\"month\":1,\"day\":5},"
            + "\"time\":{\"hour\":10,\"minute\":0,\"second\":0,\"nano\":0}}";
LocalDateTime ldt = gson.fromJson(json, LocalDateTime.class);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check composite java.time objects have required subfields
JsonObject o = JsonParser.parseString(json).getAsJsonObject();
if (!o.has("date") || !o.has("time")) {
  throw new IllegalArgumentException("LocalDateTime JSON missing date or time");
}

Try / catch

try {
  return gson.fromJson(json, LocalDateTime.class);
} catch (JsonSyntaxException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Missing ") && e.getMessage().contains("field")) {
    throw new InvalidPayloadException("Incomplete java.time JSON: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing a LocalDateTime whose JSON object has 'time' but no 'date'; an OffsetDateTime missing 'dateTime' or 'offset'; a ZonedDateTime missing 'dateTime', 'offset', or 'zone'. The producer omitted or misspelled one of the required keys.

Common situations: Producer trims null subfields; rename between API versions (e.g. 'localDateTime' vs 'dateTime'); partial deserialization of a log; client/server running different Gson versions that disagree on the field layout.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/355bdb6c646a934b.json. Report an issue: GitHub.