google/gson · error · IllegalArgumentException

Expected a Class, ParameterizedType, or GenericArrayType, bu

Error message

Expected a Class, ParameterizedType, or GenericArrayType, but <{type}> is of type {className}

What it means

GsonTypes.getRawType(Type) handles Class, ParameterizedType, GenericArrayType, TypeVariable, and WildcardType. Any other Type implementation (or null in legacy paths) is unexpected and throws IllegalArgumentException naming the actual class. It indicates a malformed/custom Type token was supplied to Gson's type resolution.

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

Solutions

  1. Inspect the Type object passed to Gson/TypeToken and replace custom Types with standard Class, ParameterizedType, or GenericArrayType.
  2. Ensure no null Type reaches Gson (defensive null-check at the API boundary).
  3. Use TypeToken.of(class) or new TypeToken<MyType<T>>(){} to produce well-formed Types.
  4. If a framework emits custom Types, write a TypeAdapter and bypass type resolution.

Example fix

// before
Type weird = myFramework.makeType(...);
TypeToken<?> token = TypeToken.get(weird); // throws

// after
TypeToken<List<String>> token = new TypeToken<List<String>>(){};
Defensive patterns

Strategy: validation

Validate before calling

if (!(type instanceof Class || type instanceof ParameterizedType || type instanceof GenericArrayType)) {
  throw new IllegalArgumentException("unsupported Type: " + type);
}

Type guard

boolean isSupportedType(Type t) {
  return t instanceof Class
      || t instanceof ParameterizedType
      || t instanceof GenericArrayType
      || t instanceof TypeVariable
      || t instanceof WildcardType;
}

Try / catch

try {
  return gson.fromJson(json, type);
} catch (IllegalArgumentException ex) {
  if (ex.getMessage().startsWith("Expected a Class, ParameterizedType")) {
    // rebuild Type via TypeToken.of(MyClass.class)
  }
  throw ex;
}

Prevention

When it happens

Trigger: Passing a custom java.lang.reflect.Type implementation, a null Type, or a Type produced by a buggy generic-resolution library; programmatic TypeToken construction with an unsupported Type variant.

Common situations: Hand-rolled TypeToken subclasses; integration with frameworks that synthesize Type objects; null returned by a broken TypeReference; JVM/bytecode-manipulation libraries emitting non-standard Types.

Related errors


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