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

  1. Match the count to rawClass.getTypeParameters().length before calling getParameterized.
  2. 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)).
  3. If building arguments dynamically, branch on typeParameters.length and assemble the varargs accordingly.
  4. 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

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


AI-assisted analysis of google/gson@310ac341f2 (2026-08-10). Data as JSON: /api/errors/47014c932deda866. Report an issue: GitHub.