{"record":{"id":"65dda026005f2ec7","repo":"google/gson","slug":"expected-a-requestedtypename-but-was-resultcl","errorCode":null,"errorMessage":"Expected a ${requestedTypeName} but was ${resultClassName}; at path ${path}","messagePattern":"Expected a (.+?) but was (.+?); at path (.+?)","errorType":"exception","errorClass":"JsonSyntaxException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java","lineNumber":1074,"sourceCode":"      @SuppressWarnings(\"unchecked\")\n      @Override\n      public <T2> TypeAdapter<T2> create(Gson gson, TypeToken<T2> typeToken) {\n        Class<? super T2> requestedType = typeToken.getRawType();\n        if (!clazz.isAssignableFrom(requestedType)) {\n          return null;\n        }\n        return (TypeAdapter<T2>)\n            new TypeAdapter<T1>() {\n              @Override\n              public void write(JsonWriter out, T1 value) throws IOException {\n                typeAdapter.write(out, value);\n              }\n\n              @Override\n              public T1 read(JsonReader in) throws IOException {\n                T1 result = typeAdapter.read(in);\n                if (result != null && !requestedType.isInstance(result)) {\n                  throw new JsonSyntaxException(\n                      \"Expected a \"\n                          + requestedType.getName()\n                          + \" but was \"\n                          + result.getClass().getName()\n                          + \"; at path \"\n                          + in.getPreviousPath());\n                }\n                return result;\n              }\n            };\n      }\n\n      @Override\n      public String toString() {\n        return \"Factory[typeHierarchy=\" + clazz.getName() + \",adapter=\" + typeAdapter + \"]\";\n      }\n    };\n  }","sourceCodeStart":1056,"sourceCodeEnd":1092,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java#L1056-L1092","documentation":"Thrown by newTypeHierarchyFactory (used by adapters like INET_ADDRESS_FACTORY) after the wrapped TypeAdapter.read() returns a value. It performs a runtime instanceof check: if the produced object is not an instance of the requestedType (the concrete subtype requested via TypeToken), it throws JsonSyntaxException. This guards against an adapter producing a broader type than the field declared.","triggerScenarios":"A field is declared as a subtype that the hierarchy adapter cannot guarantee, e.g. java.net.Inet4Address or Inet6Address but the JSON value resolves to the other family; or a custom hierarchy-registered adapter returning a base type. Concretely, INET_ADDRESS returns an InetAddress (which is concrete) so requesting Inet4Address/Inet6Address directly triggers this when the resolved address is of the wrong family.","commonSituations":"Modeling IPv4-vs-IPv6 as Inet4Address/Inet6Address fields; declaring Collection subtypes (e.g. a field of type a specific List impl) when Gson's adapter returns the generic; custom factories registered through newTypeHierarchyFactory returning superclass instances.","solutions":["Change the field type to the base type the adapter actually produces (e.g. InetAddress instead of Inet4Address).","Register a custom TypeAdapter for the exact subtype that parses and validates the address family before returning.","Pre-validate the address family (e.g. regex or InetAddress.getByName then instanceof) and reject/normalize at the boundary.","Avoid declaring fields as narrow reflection-only subtypes when the data cannot guarantee the family."],"exampleFix":"// before\npublic class Conn { public Inet4Address peer; } // may resolve as Inet6Address -> fails\n// JSON: {\"peer\":\"::1\"}\n\n// after: use the base type the adapter produces\npublic class Conn { public InetAddress peer; }\n// or validate explicitly:\nInetAddress a = InetAddress.getByName(s);\nif (!(a instanceof Inet4Address)) throw new IllegalArgumentException(\"not v4: \"+s);","handlingStrategy":"type-guard","validationCode":"// pre-validate address family before deserialization if you know the value\nString raw = jsonNode.get(\"peer\").getAsString();\nInetAddress a = InetAddress.getByName(raw);\nif (!(a instanceof Inet4Address)) {\n  throw new IllegalArgumentException(\"Not IPv4: \" + raw);\n}","typeGuard":"public static boolean isInet4Address(JsonElement e) {\n  try {\n    return InetAddress.getByName(e.getAsString()) instanceof Inet4Address;\n  } catch (Exception ex) { return false; }\n}","tryCatchPattern":"try {\n  return gson.fromJson(json, Conn.class);\n} catch (JsonSyntaxException e) {\n  if (e.getMessage().startsWith(\"Expected a \")) {\n    // narrow field type to InetAddress, or reject record\n    throw new IllegalArgumentException(\"Address family mismatch\", e);\n  }\n  throw e;\n}","preventionTips":["Prefer the base type the adapter actually returns (InetAddress) over narrow subtypes.","Validate address family at the boundary when you require a specific family.","Write parameterized tests covering both v4 and v6 inputs for IP-typed fields.","Avoid newTypeHierarchyFactory-backed subtypes unless your adapter guarantees the subtype."],"tags":["gson","type-mismatch","runtime-check","type-hierarchy-factory","inet-address","json-syntax-exception"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}