google/gson · error · JsonParseException
cannot serialize ${srcType.getName()}; did you forget to reg
Error message
cannot serialize ${srcType.getName()}; did you forget to register a subtype? What it means
Thrown during serialization by RuntimeTypeAdapterFactory when the runtime class of the object being written (value.getClass()) was never registered as a subtype. Registration keys on the exact runtime class, so an unregistered subclass of a registered type also fails. The adapter cannot pick a label, so it throws a JsonParseException. This is intentional: only explicitly allow-listed types are serialized.
Source
Thrown at extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java:303
if (delegate == null) {
throw new JsonParseException(
"cannot deserialize "
+ baseType
+ " subtype named "
+ label
+ "; did you forget to register a subtype?");
}
return delegate.fromJsonTree(jsonElement);
}
@Override
public void write(JsonWriter out, R value) throws IOException {
Class<?> srcType = value.getClass();
String label = subtypeToLabel.get(srcType);
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType);
if (delegate == null) {
throw new JsonParseException(
"cannot serialize " + srcType.getName() + "; did you forget to register a subtype?");
}
JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
if (maintainType) {
jsonElementAdapter.write(out, jsonObject);
return;
}
JsonObject clone = new JsonObject();
if (jsonObject.has(typeFieldName)) {
throw new JsonParseException(
"cannot serialize "
+ srcType.getName()
+ " because it already defines a field named "
+ typeFieldName);
}View on GitHub (pinned to 310ac341f2)
Solutions
- Register the exact runtime class: factory.registerSubtype(obj.getClass(), label).
- If you want subtypes auto-handled, ensure every concrete subclass that can appear at runtime is explicitly registered (registration is per exact class).
- Confirm you serialize using the base type token expected by the factory (e.g. gson.toJson(obj, Shape.class)).
- Centralize registration next to the class hierarchy definition so adding a subclass forces an update.
Example fix
// before factory.registerSubtype(Shape.class, "Shape"); gson.toJson(new Circle(), Shape.class); // Circle not registered -> throws // after factory.registerSubtype(Circle.class, "Circle"); gson.toJson(new Circle(), Shape.class);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the runtime class is registered before serializing
Set<Class<?>> registered = Set.of(Circle.class, Rectangle.class);
Object value = /* ... */;
if (!registered.contains(value.getClass())) {
throw new IllegalArgumentException("Unregistered subtype: " + value.getClass());
}
gson.toJson(value, Shape.class); Try / catch
try { gson.toJson(obj, Shape.class); }
catch (JsonParseException e) {
if (e.getMessage().contains("cannot serialize") && e.getMessage().contains("register a subtype")) {
// register and retry, or reject the object
} else throw e;
} Prevention
- Register every concrete runtime class, not just the parent.
- Serialize using the base type token the factory expects (Shape.class).
- Co-locate registration with the subclass definitions so adding a class forces an update.
When it happens
Trigger: Serializing a concrete subtype that was not registerSubtype'd; serializing via gson.toJson(obj, Shape.class) where obj is a subclass not registered; using the factory for the base type but passing a sibling subclass; subclass instances created by a different module/library.
Common situations: New subclass added to the domain model but the Gson factory wiring was not updated; registering a parent class and expecting subclasses to be covered (they are not, by default); serialize called with a proxied/mock subclass whose class differs from the registered one.
Related errors
- cannot serialize ${srcType.getName()} because it already def
- types and labels must be unique
- cannot deserialize ${baseType} because it does not define a
- cannot deserialize ${baseType} subtype named ${label}; did y
- Class ${typeAdapter.getClass().getName()} does not implement
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/dc40bb14e94ea9ae.
Report an issue: GitHub.