google/gson · error · UnsupportedOperationException
Attempted to serialize java.lang.Class: " + value.getName()
Error message
Attempted to serialize java.lang.Class: " + value.getName() + ". Forgot to register a type adapter?\nSee " + TroubleshootingGuide.createUrl("java-lang-class-unsupported") What it means
The built-in CLASS TypeAdapter (registered for java.lang.Class) refuses to serialize a Class object by throwing UnsupportedOperationException. Gson has no canonical textual representation for a Class reference, so serialization is intentionally blocked unless the user supplies a custom adapter. Thrown on write at line 71.
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java:71
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.regex.Pattern;
/**
* Type adapters for basic types. More complex adapters exist as separate classes in the enclosing
* package.
*/
public final class TypeAdapters {
private TypeAdapters() {
throw new UnsupportedOperationException();
}
@SuppressWarnings("rawtypes")
public static final TypeAdapter<Class> CLASS =
new TypeAdapter<Class>() {
@Override
public void write(JsonWriter out, Class value) throws IOException {
throw new UnsupportedOperationException(
"Attempted to serialize java.lang.Class: "
+ value.getName()
+ ". Forgot to register a type adapter?"
+ "\nSee "
+ TroubleshootingGuide.createUrl("java-lang-class-unsupported"));
}
@Override
public Class read(JsonReader in) throws IOException {
throw new UnsupportedOperationException(
"Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?"
+ "\nSee "
+ TroubleshootingGuide.createUrl("java-lang-class-unsupported"));
}
}.nullSafe();
public static final TypeAdapterFactory CLASS_FACTORY = newFactory(Class.class, CLASS);
View on GitHub (pinned to 8b8628c656)
Solutions
- Register a custom TypeAdapter<Class<?>> that serializes the class name (or omits it).
- Remove the Class<?> field from the serialized type, or mark it transient.
- Exclude it with @Expose(serialize=false) under excludeFieldsWithoutExposeAnnotation.
- Replace the Class<?> field with a String holding the fully-qualified name.
Example fix
// before
class ErrorReport { Class<? extends Throwable> type; String msg; }
gson.toJson(report); // UnsupportedOperationException
// after
class ErrorReport { String typeName; String msg; }
// or register adapter
registerTypeAdapter(Class.class, new TypeAdapter<Class<?>>() {
public void write(JsonWriter w, Class<?> c) throws IOException { w.value(c.getName()); }
public Class<?> read(JsonReader r) throws IOException {
try { return Class.forName(r.nextString()); }
catch (ClassNotFoundException e) { throw new JsonIOException(e); }
}
}.nullSafe()); Defensive patterns
Strategy: validation
Validate before calling
// Detect Class-typed fields before serializing
for (Field f : obj.getClass().getDeclaredFields()) {
if (f.getType() == Class.class && !Modifier.isTransient(f.getModifiers())) {
throw new IllegalStateException("Will fail: Class field " + f + " not transient and no adapter");
}
} Type guard
// Avoid carrying Class in serializable types
static boolean hasClassField(Class<?> c) {
for (Field f : c.getDeclaredFields()) if (f.getType()==Class.class) return true;
return false;
} Try / catch
try {
gson.toJson(obj);
} catch (UnsupportedOperationException e) {
if (e.getMessage().startsWith("Attempted to serialize java.lang.Class")) {
// register a Class adapter and retry, or drop the field
} else throw e;
} Prevention
- Do not declare Class<?> fields on serialized DTOs; use a String type name.
- Mark unavoidable Class fields transient.
- Register a global TypeAdapter<Class<?>> if Class round-tripping is required.
- Audit Throwable/Exception subclasses before serializing them.
When it happens
Trigger: A serializable object graph contains a field of type Class<?> (or Class) whose value is set to some Class reference, and no custom TypeAdapter<Class> is registered. Calling gson.toJson on such an object triggers CLASS.write. Also happens when serializing exceptions, proxies, or framework objects that carry a Class field.
Common situations: Logging/error DTOs holding `Class<? extends Exception> type`; ORM entities referencing entity types; reflection-heavy utilities; serializing Spring/Hibernate proxies or Throwable subclasses; forgetting that `Class` is a real serializable field type.
Related errors
- Attempted to deserialize a java.lang.Class. Forgot to regist
- Deserialization is unsupported
- Deserialization is unsupported
- JSON forbids NaN and infinities: {value}
- memberDescription + " is not accessible and ReflectionAccess
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/4f4340ed4f802fd7.json.
Report an issue: GitHub.