{"record":{"id":"5980e6d9308525b6","repo":"google/gson","slug":"missing-id-or-totalseconds-field-at-path-path","errorCode":null,"errorMessage":"Missing id or totalSeconds field; at path ${path}","messagePattern":"Missing id or totalSeconds field; at path (.+?)","errorType":"exception","errorClass":"JsonSyntaxException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java","lineNumber":319,"sourceCode":"            switch (name) {\n              case \"id\":\n                id = in.nextString();\n                break;\n              case \"totalSeconds\":\n                totalSeconds = in.nextInt();\n                break;\n              default:\n                // Ignore other fields.\n                in.skipValue();\n            }\n          }\n          in.endObject();\n          if (id != null) {\n            return ZoneId.of(id);\n          } else if (totalSeconds != null) {\n            return ZoneOffset.ofTotalSeconds(totalSeconds);\n          } else {\n            throw new JsonSyntaxException(\n                \"Missing id or totalSeconds field; at path \" + in.getPreviousPath());\n          }\n        }\n\n        @Override\n        public void write(JsonWriter out, ZoneId value) throws IOException {\n          if (value instanceof ZoneOffset) {\n            out.beginObject();\n            out.name(\"totalSeconds\");\n            out.value(((ZoneOffset) value).getTotalSeconds());\n            out.endObject();\n          } else {\n            out.beginObject();\n            out.name(\"id\");\n            out.value(value.getId());\n            out.endObject();\n          }\n        }","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java#L301-L337","documentation":"Gson's built-in ZoneId adapter reads an object expecting exactly one of two discriminant fields: \"id\" (for region-based zones like 'America/New_York') or \"totalSeconds\" (for ZoneOffset). If the object contains neither, deserialization cannot proceed and throws JsonSyntaxException. This mirrors the legacy reflective serialization of java.time.ZoneId from JDK 21.","triggerScenarios":"Deserializing a ZoneId/ZoneOffset from a JSON object such as \"{}\" or \"{\\\"foo\\\":1}\" that lacks both 'id' and 'totalSeconds'. Occurs when the JSON was produced by a non-Gson serializer or hand-edited.","commonSituations":"Interoperating with systems that serialize ZoneId as a plain string instead of an object; upgrading from an older Gson whose reflective encoding differed; payloads trimmed for size.","solutions":["Ensure the JSON object contains either {\"id\":\"America/New_York\"} or {\"totalSeconds\":3600}.","Register a custom TypeAdapter<ZoneId> that accepts the producer's representation (e.g. a bare string).","Validate the JSON shape (presence of id/totalSeconds) before calling fromJson.","Switch the producer to emit Gson-compatible objects."],"exampleFix":"// before: {}\nGson().fromJson(\"{}\", ZoneId::class.java) // throws\n\n// after\nGson().fromJson(\"{\\\"id\\\":\\\"America/New_York\\\"}\", ZoneId::class.java)","handlingStrategy":"validation","validationCode":"// Validate the ZoneId object shape before deserializing\nstatic boolean isValidZoneIdJson(JsonObject o) {\n  return o.has(\"id\") || o.has(\"totalSeconds\");\n}\n// Or register a custom adapter accepting a bare string\nclass ZoneIdAdapter extends TypeAdapter<ZoneId> {\n  public void write(JsonWriter out, ZoneId v) throws IOException { out.value(v.getId()); }\n  public ZoneId read(JsonReader in) throws IOException { return ZoneId.of(in.nextString()); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  gson.fromJson(json, ZoneId.class);\n} catch (JsonSyntaxException e) {\n  if (e.getMessage().startsWith(\"Missing id or totalSeconds\")) {\n    // producer emitted a different ZoneId shape; switch adapter\n    log.warn(\"ZoneId JSON missing id/totalSeconds: {}\", e.getMessage());\n  }\n  throw e;\n}","preventionTips":["Produce ZoneId as a string id and register a custom adapter for cross-system interop.","Validate object shape before deserializing java.time zones.","Document Gson's expected ZoneId encoding for producers.","Pin Gson version to avoid encoding drift."],"tags":["java-time","zone","deserialization","schema"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}