{"record":{"id":"8364825de424d404","repo":"google/gson","slug":"rawtype-must-be-of-type-class-but-was","errorCode":null,"errorMessage":"rawType must be of type Class, but was {}","messagePattern":"rawType must be of type Class, but was (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/reflect/TypeToken.java","lineNumber":393,"sourceCode":"   *\n   * As seen here the result is a {@code TypeToken<?>}; this method cannot provide any type-safety,\n   * and care must be taken to pass in the correct number of type arguments.\n   *\n   * <p>If {@code rawType} is a non-generic class and no type arguments are provided, this method\n   * simply delegates to {@link #get(Class)} and creates a {@code TypeToken(Class)}.\n   *\n   * @throws IllegalArgumentException If {@code rawType} is not of type {@code Class}, or if the\n   *     type arguments are invalid for the raw type\n   */\n  public static TypeToken<?> getParameterized(Type rawType, Type... typeArguments) {\n    Objects.requireNonNull(rawType);\n    Objects.requireNonNull(typeArguments);\n\n    // Perform basic validation here because this is the only public API where users\n    // can create malformed parameterized types\n    if (!(rawType instanceof Class)) {\n      // See also https://bugs.openjdk.org/browse/JDK-8250659\n      throw new IllegalArgumentException(\"rawType must be of type Class, but was \" + rawType);\n    }\n    Class<?> rawClass = (Class<?>) rawType;\n    TypeVariable<?>[] typeVariables = rawClass.getTypeParameters();\n\n    int expectedArgsCount = typeVariables.length;\n    int actualArgsCount = typeArguments.length;\n    if (actualArgsCount != expectedArgsCount) {\n      throw new IllegalArgumentException(\n          rawClass.getName()\n              + \" requires \"\n              + expectedArgsCount\n              + \" type arguments, but got \"\n              + actualArgsCount);\n    }\n\n    // For legacy reasons create a TypeToken(Class) if the type is not generic\n    if (typeArguments.length == 0) {\n      return get(rawClass);","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/reflect/TypeToken.java#L375-L411","documentation":"Thrown by TypeToken.getParameterized when the rawType argument is not an instance of java.lang.Class (e.g. a ParameterizedType, GenericArrayType, TypeVariable, or WildcardType). getParameterized validates rawType explicitly because it is the only public API where users can construct malformed parameterized types; JDK bug JDK-8250659 is referenced.","triggerScenarios":"Calling TypeToken.getParameterized(someType, ...) where someType is itself a parameterized type (like List<String>.class equivalent) or a GenericArrayType, rather than a plain Class. Example: TypeToken.getParameterized(new TypeToken<List<String>>(){}.getType(), String.class) passes a ParameterizedType as rawType.","commonSituations":"Mistakenly passing a Type's toString or a nested generic type where the raw class is expected; chained calls that hand a resolved generic type instead of the erasure; copying patterns from getParameterized examples and feeding the wrong slot; confusion between raw type and parameterized type.","solutions":["Pass the raw Class (e.g. Map.class, List.class), not a parameterized Type. If you have a Type, get its erasure via GsonTypes.getRawType or Class.forName first.","For nested generics, build from the inside out with getParameterized and pass the result's getType() only as a type argument, never as rawType.","If you already hold a Type, use TypeToken.get(type) instead of getParameterized.","Add a runtime assertion `assert rawType instanceof Class` before calling to fail fast in tests."],"exampleFix":"// before (broken)\nType listType = new TypeToken<List<String>>(){}.getType();\nTypeToken<?> t = TypeToken.getParameterized(listType, String.class); // listType not a Class -> throws\n\n// after: pass the raw Class\nTypeToken<?> t = TypeToken.getParameterized(List.class, String.class);\n\n// or, if you already have a Type, use TypeToken.get:\nTypeToken<?> t = TypeToken.get(listType);\n\n// for Map<String, List<Integer>>:\nTypeToken<?> inner = TypeToken.getParameterized(List.class, Integer.class);\nTypeToken<?> outer = TypeToken.getParameterized(Map.class, String.class, inner.getType());","handlingStrategy":"validation","validationCode":"// guard before calling getParameterized\nif (!(rawType instanceof Class)) {\n  // either resolve erasure, or use TypeToken.get(rawType)\n  rawType = rawType instanceof ParameterizedType\n      ? ((ParameterizedType) rawType).getRawType()\n      : rawType;\n}\nif (!(rawType instanceof Class)) {\n  throw new IllegalArgumentException(\"rawType must be Class, got: \" + rawType);\n}","typeGuard":"public static boolean isRawClass(Type t) {\n  return t instanceof Class;\n}","tryCatchPattern":"try {\n  return TypeToken.getParameterized(rawType, args);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"rawType must be of type Class\")) {\n    // fall back: if it's already a resolved Type, use TypeToken.get\n    return TypeToken.get(rawType);\n  }\n  throw e;\n}","preventionTips":["Always pass a Class as the first argument to getParameterized.","If you already have a Type, use TypeToken.get(type).","Build nested generics inside-out, passing inner getType() as a type argument only.","Add an `assert rawType instanceof Class` in test code to fail fast."],"tags":["gson","type-token","generics","parameterized-type","illegal-argument"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}