{"record":{"id":"e10ab86026a65c18","repo":"google/gson","slug":"raw-type-is-not-supported-because-it-requires-s","errorCode":null,"errorMessage":"Raw type {} is not supported because it requires specifying an owner type","messagePattern":"Raw type (.+?) is not supported because it requires specifying an owner type","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/reflect/TypeToken.java","lineNumber":416,"sourceCode":"    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\");\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","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/reflect/TypeToken.java#L398-L434","documentation":"Thrown by TypeToken.getParameterized when GsonTypes.requiresOwnerType(rawType) returns true (TypeToken.java:414-420). Some generic classes are inner (non-static nested) classes whose generic signature requires an enclosing instance type, and getParameterized cannot supply an owner type, so creating such a ParameterizedType would be ambiguous. The check runs before delegating to ParameterizedTypeImpl to surface a clear error instead of a misleading internal failure.","triggerScenarios":"Calling TypeToken.getParameterized(SomeOuter.SomeInner.class, ...) where SomeInner is a non-static inner (member) class declaring its own type parameters. Also triggered by generic inner classes of classes like java.util.Map.Entry used as a raw type with type arguments when the reflection API demands an owner.","commonSituations":"Reflecting over framework-defined nested generic types (e.g. entry subclasses, builders defined as inner classes); using a library whose public API exposes a parameterized non-static nested class; converting code that worked with TypeToken<Map<K,V>> to a custom nested builder type.","solutions":["Make the nested class static (preferred) so it no longer requires an owner type.","If you cannot change the class, construct the ParameterizedType manually via java.lang.reflect.ParameterizedType or GsonTypes.newParameterizedTypeWithOwner(owner, raw, args) supplying the owner type.","Use an anonymous TypeToken subclass new TypeToken<Outer.Inner<X>>(){} when the type is known at compile time.","Prefer a top-level class or interface for the generic contract."],"exampleFix":"// before\nclass Builder<T> { ... } // non-static inner of Outer\nTypeToken<?> t = TypeToken.getParameterized(Outer.Builder.class, String.class);\n\n// after\nstatic class Builder<T> { ... } // static nested, no owner needed\nTypeToken<?> t = TypeToken.getParameterized(Outer.Builder.class, String.class);","handlingStrategy":"validation","validationCode":"Class<?> raw = SomeInner.class;\nif (Modifier.isStatic(raw.getModifiers()) == false && raw.getEnclosingClass() != null\n    && raw.getTypeParameters().length > 0) {\n  // likely requires owner; avoid getParameterized, build manually with owner\n}\nTypeToken<?> t = TypeToken.getParameterized(raw, args);","typeGuard":"static boolean likelyNeedsOwnerType(Class<?> raw) {\n  return !Modifier.isStatic(raw.getModifiers())\n      && raw.getEnclosingClass() != null;\n}","tryCatchPattern":"try {\n  return TypeToken.getParameterized(raw, args);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"owner type\")) {\n    return TypeToken.get(GsonTypes.newParameterizedTypeWithOwner(owner, raw, args));\n  }\n  throw e;\n}","preventionTips":["Prefer static nested classes for generic types used with reflection.","If you must use a non-static inner class, supply an explicit owner type.","Cache resolved TypeTokens rather than reconstructing on every call."],"tags":["java","gson","generics","typetoken","inner-class"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}