google/gson · error · IllegalArgumentException
Expected a Class, ParameterizedType, or GenericArrayType…
Error message
Expected a Class, ParameterizedType, or GenericArrayType, but <${type}> is of type ${className} What it means
Thrown by GsonTypes.getRawType() when the given Type is none of the supported implementations (Class, ParameterizedType, GenericArrayType, TypeVariable, WildcardType). This indicates an unsupported or custom Type implementation was passed to Gson's type-resolution machinery. The message names the type and its class.
Solutions
- Use standard types via TypeToken: new TypeToken<MyClass<String>>(){}.getType()
- Register a TypeAdapter for the type to bypass raw type resolution entirely
- Replace the custom Type with a standard ParameterizedType produced by GsonTypes.newParameterizedTypeWithOwner
Example fix
// before
gson.fromJson(json, myCustomTypeImpl); // custom Type
// after
gson.fromJson(json, new TypeToken<MyClass<String>>(){}.getType()); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate that a Type is one Gson's getRawType supports before using it
static boolean isSupportedRawType(Type type) {
return type instanceof Class
|| type instanceof ParameterizedType
|| type instanceof GenericArrayType
|| type instanceof TypeVariable
|| type instanceof WildcardType;
}
if (!isSupportedRawType(myType)) {
throw new IllegalArgumentException("Unsupported Type implementation: " + type.getClass());
} Type guard
static boolean isStandardType(Type type) {
return type == null
|| type instanceof Class
|| type instanceof ParameterizedType
|| type instanceof GenericArrayType
|| type instanceof TypeVariable
|| type instanceof WildcardType;
} Prevention
- Always use TypeToken to create Type instances — it produces standard ParameterizedType implementations
- Never pass hand-rolled or third-party Type objects to Gson without registering a TypeAdapter
- If you must use a custom Type, register a TypeAdapter for it to bypass getRawType
When it happens
Trigger: Passing a custom java.lang.reflect.Type implementation that doesn't implement any of the standard subinterfaces to Gson's type resolution, TypeToken, or reflection-based constructors.
Common situations: Custom Type implementations from third-party libraries; incorrect TypeToken subclassing; hand-built Type objects that bypass the standard interfaces.
Related errors
- At most one lower bound is supported
- is not the same as or a subtype of
- Exactly one upper bound must be specified
- Must specify owner type for
- Primitive type is not allowed
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/33a2290da320e4e0.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/GsonTypes.java:158
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
} else if (type instanceof TypeVariable) {
// we could use the variable's bounds, but that won't work if there are multiple.
// having a raw type that's more general than necessary is okay
return Object.class;
} else if (type instanceof WildcardType) {
Type[] bounds = ((WildcardType) type).getUpperBounds();
// Currently the JLS only permits one bound for wildcards so using first bound is safe
assert bounds.length == 1;
return getRawType(bounds[0]);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException(
"Expected a Class, ParameterizedType, or GenericArrayType, but <"
+ type
+ "> is of type "
+ className);
}
}
private static boolean equal(Object a, Object b) {
return Objects.equals(a, b);
}
/** Returns true if {@code a} and {@code b} are equal. */
public static boolean equals(Type a, Type b) {
@SuppressWarnings("ReferenceEquality")
boolean areSame = a == b;
if (areSame) {
// also handles (a == null && b == null)
return true;View on GitHub (pinned to 310ac341f2)