google/gson · error · IllegalArgumentException

rawClass.getName() + " requires " + expectedArgsCount + " ty

Error message

rawClass.getName() + " requires " + expectedArgsCount + " type arguments, but got " + actualArgsCount

What it means

Thrown by TypeToken.getParameterized when the number of type arguments supplied does not equal the number declared by the raw class (rawClass.getTypeParameters().length). This is an explicit count check before any attempt to build the parameterized type, giving a clear error instead of a downstream ArrayIndexOutOfBoundsException.

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 8b8628c656)

Solutions

  1. Match the count to rawClass.getTypeParameters().length; e.g. for Map pass exactly two type arguments.
  2. If the type arguments are dynamic, read rawClass.getTypeParameters().length first and validate before calling.
  3. For a non-generic class pass no type arguments (the method delegates to get(rawClass)).
  4. Double-check imports: using Map vs Map.Entry changes the expected arity.

Example fix

// before
TypeToken.getParameterized(Map.class, String.class); // Map needs 2

// after
TypeToken.getParameterized(Map.class, String.class, Integer.class);
Defensive patterns

Strategy: validation

Validate before calling

void requireArity(Class<?> rawClass, Type... args) {
  int expected = rawClass.getTypeParameters().length;
  if (args.length != expected) {
    throw new IllegalArgumentException(rawClass.getName() + " needs " + expected + " args, got " + args.length);
  }
}
// call before TypeToken.getParameterized(rawClass, args)

Prevention

When it happens

Trigger: Calling getParameterized with too few or too many arguments, e.g. TypeToken.getParameterized(Map.class, String.class) (Map needs 2) or TypeToken.getParameterized(List.class, String.class, Integer.class) (List needs 1).

Common situations: Wrapping collection types in helper methods where the arity is dynamic; copy-paste errors when changing the raw type (e.g. switching from List to Map) without updating the arguments; passing a varargs array of unknown length.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/0e09f0868ce0a61c.json. Report an issue: GitHub.