google/gson · error · IllegalArgumentException
Primitive type is not allowed
Error message
Primitive type is not allowed
What it means
Thrown by GsonTypes.checkNotPrimitive when a Type argument supplied to a ParameterizedTypeImpl is a primitive Class (int.class, boolean.class, etc.). Reflection Type mirrors cannot legally represent primitive types; only their boxed/wrapper types or reference component types are valid in parameterized positions. Gson enforces this so it never builds an internally inconsistent Type token.
Solutions
- Replace the primitive Class with its wrapper, e.g. int.class -> Integer.class, boolean.class -> Boolean.class.
- For primitive arrays use the array type int[].class (an Object subclass) rather than a primitive class inside a parameterized position.
- If generating types reflectively, normalize with a helper: Class<?> boxed = raw.isPrimitive() ? box(raw) : raw before passing as a type argument.
Example fix
// before Type t = TypeToken.getParameterized(Collection.class, int.class).getType(); // after Type t = TypeToken.getParameterized(Collection.class, Integer.class).getType();
Defensive patterns
Strategy: validation
Validate before calling
private static boolean isValidTypeArg(Type t) {
return !(t instanceof Class<?> c && c.isPrimitive());
}
// before building: if (!isValidTypeArg(arg)) arg = box((Class<?>) arg); Type guard
static Type boxIfPrimitive(Type t) {
if (t instanceof Class<?> c && c.isPrimitive()) {
if (c == int.class) return Integer.class;
if (c == long.class) return Long.class;
if (c == boolean.class) return Boolean.class;
if (c == double.class) return Double.class;
if (c == float.class) return Float.class;
if (c == short.class) return Short.class;
if (c == byte.class) return Byte.class;
if (c == char.class) return Character.class;
if (c == void.class) return Void.class;
}
return t;
} Prevention
- Never pass primitive .class literals as generic type arguments; always use their wrappers.
- When building TypeTokens reflectively, run every Class through a box() helper before use.
- Prefer TypeToken.getParameterized over manually constructing parameterized types.
When it happens
Trigger: Constructing a parameterized Type whose actual type argument is a primitive Class, e.g. passing int.class as a type argument into GsonTypes$ParameterizedTypeImpl (called at GsonTypes.java:531). Reachable via TypeToken.getParameterized(raw, int.class), TypeToken<Collection<int>>, or a manually built ParameterizedType with a primitive in the args array.
Common situations: Building TypeTokens for collections/primitive arrays by hand; porting code that assumed int.class was a valid Type argument; reflective generics code that iterates Class objects and forgets to box primitives before constructing a parameterized type.
Related errors
- Must specify owner type for
- At most one lower bound is supported
- Exactly one upper bound must be specified
- Must only create direct subclasses of TypeToken
- rawType must be of type Class, but was
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/9eb0716caa00bdde.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/GsonTypes.java:492
if (toFind.equals(array[i])) {
return i;
}
}
throw new NoSuchElementException();
}
/**
* Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by
* a class.
*/
private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) {
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
return genericDeclaration instanceof Class ? (Class<?>) genericDeclaration : null;
}
static void checkNotPrimitive(Type type) {
if (type instanceof Class<?> && ((Class<?>) type).isPrimitive()) {
throw new IllegalArgumentException("Primitive type is not allowed");
}
}
/**
* Whether an {@linkplain ParameterizedType#getOwnerType() owner type} must be specified when
* constructing a {@link ParameterizedType} for {@code rawType}.
*
* <p>Note that this method might not require an owner type for all cases where Java reflection
* would create parameterized types with owner type.
*/
public static boolean requiresOwnerType(Type rawType) {
if (rawType instanceof Class<?>) {
Class<?> rawTypeAsClass = (Class<?>) rawType;
return !Modifier.isStatic(rawTypeAsClass.getModifiers())
&& rawTypeAsClass.getDeclaringClass() != null;
}
return false;
}View on GitHub (pinned to 310ac341f2)