{"id":"04348b5807ea6f85","repo":"google/gson","slug":"type-argument-typeargument-does-not-satisf","errorCode":null,"errorMessage":"Type argument \" + typeArgument + \" does not satisfy bounds for type variable \" + typeVariable + \" declared by \" + rawType","messagePattern":"Type argument \" \\+ typeArgument \\+ \" does not satisfy bounds for type variable \" \\+ typeVariable \\+ \" declared by \" \\+ rawType","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/reflect/TypeToken.java","lineNumber":432,"sourceCode":"    // 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\");\n    }\n\n    for (int i = 0; i < expectedArgsCount; i++) {\n      Type typeArgument =\n          Objects.requireNonNull(typeArguments[i], \"Type argument must not be null\");\n      Class<?> rawTypeArgument = GsonTypes.getRawType(typeArgument);\n      TypeVariable<?> typeVariable = typeVariables[i];\n\n      for (Type bound : typeVariable.getBounds()) {\n        Class<?> rawBound = GsonTypes.getRawType(bound);\n\n        if (!rawBound.isAssignableFrom(rawTypeArgument)) {\n          throw new IllegalArgumentException(\n              \"Type argument \"\n                  + typeArgument\n                  + \" does not satisfy bounds for type variable \"\n                  + typeVariable\n                  + \" declared by \"\n                  + rawType);\n        }\n      }\n    }\n\n    return new TypeToken<>(GsonTypes.newParameterizedTypeWithOwner(null, rawClass, typeArguments));\n  }\n\n  /**\n   * Gets type literal for the array type whose elements are all instances of {@code componentType}.\n   */\n  public static TypeToken<?> getArray(Type componentType) {\n    return new TypeToken<>(GsonTypes.arrayOf(componentType));","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/reflect/TypeToken.java#L414-L450","documentation":"Thrown by TypeToken.getParameterized after checking each type argument against the bounds of the corresponding type variable (TypeVariable.getBounds()). If the raw type argument does not satisfy an upper bound (e.g. <T extends Comparable<T>>), getParameterized rejects it so that downstream serialization does not fail in confusing ways or produce a ClassCastException.","triggerScenarios":"Passing a type argument that violates the declared bound, e.g. class Box<T extends Number>{}; TypeToken.getParameterized(Box.class, String.class). The bound Number is not assignable from String, so the check at TypeToken.java:431 fails.","commonSituations":"Building parameterized tokens from user-driven Class objects where the caller can pass anything; refactoring a generic class to add a bound and forgetting to update callers; using libraries that constrain type parameters heavily (e.g. enums, Comparable).","solutions":["Pass a type argument that satisfies the bound (e.g. for <T extends Number> pass Integer.class, BigDecimal.class, etc.).","Loosen or remove the type bound on the generic class if the constraint is no longer correct.","Validate the candidate Class against the bound programmatically before calling getParameterized.","If the bound is intentional but you must accept arbitrary types, redesign the API to work with Object/raw types outside Gson."],"exampleFix":"// before\nclass Box<T extends Number> { T value; }\nTypeToken.getParameterized(Box.class, String.class); // throws\n\n// after\nTypeToken.getParameterized(Box.class, Integer.class);","handlingStrategy":"validation","validationCode":"boolean satisfiesBounds(Class<?> rawClass, Type typeArg) {\n  Class<?> rawArg = com.google.gson.internal.GsonTypes.getRawType(typeArg);\n  for (java.lang.reflect.TypeVariable<?> tv : rawClass.getTypeParameters()) {\n    for (Type bound : tv.getBounds()) {\n      Class<?> rawBound = com.google.gson.internal.GsonTypes.getRawType(bound);\n      if (!rawBound.isAssignableFrom(rawArg)) return false;\n    }\n  }\n  return true;\n}\n// call before TypeToken.getParameterized(rawClass, typeArg)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mirror the generic class's type bounds in your calling code's contracts.","When adding a bound to an existing generic class, audit all getParameterized callers.","Unit-test each (rawClass, typeArg) pair your code builds to catch bound violations early.","Document bounds on factories that construct parameterized tokens."],"tags":["gson","typetoken","generics","type-bounds","validation"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}