google/gson · error · JsonSyntaxException
Expected a ${requestedTypeName} but was ${resultClassName};
Error message
Expected a ${requestedTypeName} but was ${resultClassName}; at path ${path} What it means
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.
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java:1074
@SuppressWarnings("unchecked")
@Override
public <T2> TypeAdapter<T2> create(Gson gson, TypeToken<T2> typeToken) {
Class<? super T2> requestedType = typeToken.getRawType();
if (!clazz.isAssignableFrom(requestedType)) {
return null;
}
return (TypeAdapter<T2>)
new TypeAdapter<T1>() {
@Override
public void write(JsonWriter out, T1 value) throws IOException {
typeAdapter.write(out, value);
}
@Override
public T1 read(JsonReader in) throws IOException {
T1 result = typeAdapter.read(in);
if (result != null && !requestedType.isInstance(result)) {
throw new JsonSyntaxException(
"Expected a "
+ requestedType.getName()
+ " but was "
+ result.getClass().getName()
+ "; at path "
+ in.getPreviousPath());
}
return result;
}
};
}
@Override
public String toString() {
return "Factory[typeHierarchy=" + clazz.getName() + ",adapter=" + typeAdapter + "]";
}
};
}View on GitHub (pinned to 310ac341f2)
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.
Example fix
// before
public class Conn { public Inet4Address peer; } // may resolve as Inet6Address -> fails
// JSON: {"peer":"::1"}
// after: use the base type the adapter produces
public class Conn { public InetAddress peer; }
// or validate explicitly:
InetAddress a = InetAddress.getByName(s);
if (!(a instanceof Inet4Address)) throw new IllegalArgumentException("not v4: "+s); Defensive patterns
Strategy: type-guard
Validate before calling
// pre-validate address family before deserialization if you know the value
String raw = jsonNode.get("peer").getAsString();
InetAddress a = InetAddress.getByName(raw);
if (!(a instanceof Inet4Address)) {
throw new IllegalArgumentException("Not IPv4: " + raw);
} Type guard
public static boolean isInet4Address(JsonElement e) {
try {
return InetAddress.getByName(e.getAsString()) instanceof Inet4Address;
} catch (Exception ex) { return false; }
} Try / catch
try {
return gson.fromJson(json, Conn.class);
} catch (JsonSyntaxException e) {
if (e.getMessage().startsWith("Expected a ")) {
// narrow field type to InetAddress, or reject record
throw new IllegalArgumentException("Address family mismatch", e);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed parsing '${s}' as InetAddress; at path ${path}; to al
- Failed parsing '${s}' as BigInteger; at path ${path}
- Failed parsing '${s}' as UUID; at path ${path}
- Failed parsing '${s}' as Currency; at path ${path}
- Failed parsing '{}' as SQL Date; at path {}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/65dda026005f2ec7.
Report an issue: GitHub.