google/gson · error · IllegalArgumentException
{} requires {} type arguments, but got {}
Error message
{} requires {} type arguments, but got {} What it means
Thrown by TypeToken.getParameterized(Type, Type...) when the number of type arguments supplied does not equal the count declared by the raw class's type parameters. The method computes expectedArgsCount = rawClass.getTypeParameters().length and compares it to typeArguments.length at TypeToken.java:400-407, failing fast rather than producing a malformed ParameterizedType. It exists because getParameterized is the only public entry point where callers can hand-craft generic types, so argument arity must be validated explicitly.
Source
Thrown at gson/src/main/java/com/google/gson/reflect/TypeToken.java:401
* type arguments are invalid for the raw type
*/
public static TypeToken<?> getParameterized(Type rawType, Type... typeArguments) {
Objects.requireNonNull(rawType);
Objects.requireNonNull(typeArguments);
// Perform basic validation here because this is the only public API where users
// can create malformed parameterized types
if (!(rawType instanceof Class)) {
// See also https://bugs.openjdk.org/browse/JDK-8250659
throw new IllegalArgumentException("rawType must be of type Class, but was " + rawType);
}
Class<?> rawClass = (Class<?>) rawType;
TypeVariable<?>[] typeVariables = rawClass.getTypeParameters();
int expectedArgsCount = typeVariables.length;
int actualArgsCount = typeArguments.length;
if (actualArgsCount != expectedArgsCount) {
throw new IllegalArgumentException(
rawClass.getName()
+ " requires "
+ expectedArgsCount
+ " type arguments, but got "
+ actualArgsCount);
}
// For legacy reasons create a TypeToken(Class) if the type is not generic
if (typeArguments.length == 0) {
return get(rawClass);
}
// Check for this here to avoid misleading exception thrown by ParameterizedTypeImpl
if (GsonTypes.requiresOwnerType(rawType)) {
throw new IllegalArgumentException(
"Raw type "
+ rawClass.getName()
+ " is not supported because it requires specifying an owner type");View on GitHub (pinned to 310ac341f2)
Solutions
- Match the count to rawClass.getTypeParameters().length before calling getParameterized.
- For Map use exactly two arguments (key then value); for List/Set use one; for a non-generic class pass zero (or just use TypeToken.get(clazz)).
- If building arguments dynamically, branch on typeParameters.length and assemble the varargs accordingly.
- Add a unit test asserting the constructed TypeToken.toString() equals the expected generic signature.
Example fix
// before TypeToken<?> t = TypeToken.getParameterized(Map.class, String.class); // after TypeToken<?> t = TypeToken.getParameterized(Map.class, String.class, Integer.class);
Defensive patterns
Strategy: validation
Validate before calling
Class<?> raw = Map.class;
int expected = raw.getTypeParameters().length;
Type[] args = { String.class, Integer.class };
if (args.length != expected) {
throw new IllegalArgumentException(
raw.getName() + " needs " + expected + " args, got " + args.length);
}
TypeToken<?> t = TypeToken.getParameterized(raw, args); Type guard
static boolean hasMatchingArity(Class<?> raw, Type[] args) {
return raw.getTypeParameters().length == args.length;
} Try / catch
try {
return TypeToken.getParameterized(raw, args);
} catch (IllegalArgumentException e) {
throw new InvalidTypeTokenException(raw, args, e);
} Prevention
- Wrap getParameterized in a helper that asserts arity from getTypeParameters().
- Add unit tests covering each generic type you construct dynamically.
- Document the expected argument count at every dynamic-construction call site.
When it happens
Trigger: Calling TypeToken.getParameterized(Map.class, String.class) (Map declares K,V so needs 2 args but got 1), or getParameterized(List.class, String.class, Integer.class) (List has one type parameter E but got 2). Also triggered when rawType is a non-generic class and typeArguments is non-empty but non-zero, or when passing the wrong count after dynamically building the varargs array.
Common situations: Dynamically constructing TypeTokens from runtime Class objects (e.g. building a Map<K,V> token from request metadata) and miscounting args; copy-paste from a List example to a Map without adding the second argument; off-by-one when spreading a varargs array; refactor that changed the target collection type without updating the argument list.
Related errors
- Raw type {} is not supported because it requires specifying
- Type argument {} does not satisfy bounds for type variable {
- Invalid nesting limit: {}
- Numeric values must be finite, but was {}
- Primitive type is not allowed
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/47014c932deda866.
Report an issue: GitHub.