{"record":{"id":"47014c932deda866","repo":"google/gson","slug":"requires-type-arguments-but-got","errorCode":null,"errorMessage":"{} requires {} type arguments, but got {}","messagePattern":"(.+?) requires (.+?) type arguments, but got (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/reflect/TypeToken.java","lineNumber":401,"sourceCode":"   *     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);\n    }\n\n    // Check for this here to avoid misleading exception thrown by ParameterizedTypeImpl\n    if (GsonTypes.requiresOwnerType(rawType)) {\n      throw new IllegalArgumentException(\n          \"Raw type \"\n              + rawClass.getName()\n              + \" is not supported because it requires specifying an owner type\");","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/reflect/TypeToken.java#L383-L419","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nTypeToken<?> t = TypeToken.getParameterized(Map.class, String.class);\n\n// after\nTypeToken<?> t = TypeToken.getParameterized(Map.class, String.class, Integer.class);","handlingStrategy":"validation","validationCode":"Class<?> raw = Map.class;\nint expected = raw.getTypeParameters().length;\nType[] args = { String.class, Integer.class };\nif (args.length != expected) {\n  throw new IllegalArgumentException(\n      raw.getName() + \" needs \" + expected + \" args, got \" + args.length);\n}\nTypeToken<?> t = TypeToken.getParameterized(raw, args);","typeGuard":"static boolean hasMatchingArity(Class<?> raw, Type[] args) {\n  return raw.getTypeParameters().length == args.length;\n}","tryCatchPattern":"try {\n  return TypeToken.getParameterized(raw, args);\n} catch (IllegalArgumentException e) {\n  throw new InvalidTypeTokenException(raw, args, e);\n}","preventionTips":["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."],"tags":["java","gson","generics","typetoken","validation"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}