{"id":"76c167e889408006","repo":"google/gson","slug":"must-specify-owner-type-for-rawtype","errorCode":null,"errorMessage":"Must specify owner type for {rawType}","messagePattern":"Must specify owner type for (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/GsonTypes.java","lineNumber":523,"sourceCode":"      Class<?> rawTypeAsClass = (Class<?>) rawType;\n      return !Modifier.isStatic(rawTypeAsClass.getModifiers())\n          && rawTypeAsClass.getDeclaringClass() != null;\n    }\n    return false;\n  }\n\n  private static final class ParameterizedTypeImpl implements ParameterizedType {\n    private final Type ownerType;\n\n    private final Type rawType;\n\n    private final Type[] typeArguments;\n\n    ParameterizedTypeImpl(Type ownerType, Class<?> rawType, Type... typeArguments) {\n      requireNonNull(rawType);\n\n      if (ownerType == null && requiresOwnerType(rawType)) {\n        throw new IllegalArgumentException(\"Must specify owner type for \" + rawType);\n      }\n\n      this.ownerType = ownerType == null ? null : canonicalize(ownerType);\n      this.rawType = canonicalize(rawType);\n      this.typeArguments = typeArguments.clone();\n      for (int t = 0, length = this.typeArguments.length; t < length; t++) {\n        requireNonNull(this.typeArguments[t]);\n        checkNotPrimitive(this.typeArguments[t]);\n        this.typeArguments[t] = canonicalize(this.typeArguments[t]);\n      }\n    }\n\n    @Override\n    public Type[] getActualTypeArguments() {\n      return typeArguments.clone();\n    }\n\n    @Override","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/GsonTypes.java#L505-L541","documentation":"Thrown by ParameterizedTypeImpl's constructor (GsonTypes) when an owner type is null but requiresOwnerType(rawType) returns true. A non-static inner/nested class implicitly carries a reference to its enclosing instance, so a parameterized type for it (e.g. Outer<String>.Inner) must declare which enclosing instance type owns it. Omitting the owner produces an ill-formed ParameterizedType that Java reflection would never create.","triggerScenarios":"Constructing a parameterized type for a non-static nested class (has a declaring class and is not static) without supplying ownerType. Triggered via TypeToken.getParameterized(Inner.class, ...) where Inner is an inner class, or by Gson resolving a field whose generic type is Outer<X>.Inner while resolving ownerType to null.","commonSituations":"Modeling JSON as a non-static inner class; using nested generic types like class Outer<T> { class Inner { T value; } } and serializing Inner directly; migration from static nested classes to inner classes without updating type tokens.","solutions":["Make the nested class static (preferred): add the 'static' modifier so no owner type is required.","Supply the owner type when building the ParameterizedType, e.g. TypeToken.getParameterized(ownerType, Inner.class, args).","Move the nested class to a top-level class to avoid the owner-type requirement entirely."],"exampleFix":"// before\nclass Outer<T> { class Inner { T value; } }\nType t = TypeToken.getParameterized(Outer.Inner.class, String.class).getType();\n\n// after: make it static\nclass Outer<T> { static class Inner<T> { T value; } }","handlingStrategy":"validation","validationCode":"static boolean needsOwner(Class<?> raw) {\n  return !Modifier.isStatic(raw.getModifiers()) && raw.getDeclaringClass() != null;\n}\n// usage: if (needsOwner(rawType)) throw new IllegalStateException(\"provide ownerType or make static\");","typeGuard":"null","tryCatchPattern":"try {\n  TypeToken.getParameterized(Inner.class, args).getType();\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"owner type\")) {\n    // fall back: make the nested class static or supply owner\n    throw new IllegalStateException(\"Inner class needs ownerType; make it static\", e);\n  } else throw e;\n}","preventionTips":["Prefer static nested classes for Gson model types.","When modeling inner generic classes, always pass the owner type explicitly.","Add a project convention: model classes must be top-level or static-nested."],"tags":["gson","generics","reflection","inner-class","owner-type"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}