google/gson · error · IllegalArgumentException
Must specify owner type for
Error message
Must specify owner type for ${rawType} What it means
Thrown when building a ParameterizedTypeImpl for a non-static inner (member) class without supplying an ownerType. Java's type system requires an enclosing instance type for non-static nested classes (GsonTypes.requiresOwnerType returns true when the class has a declaring class and is not static). Gson refuses to silently fabricate one because doing so would create an ambiguous, possibly incorrect Type.
Solutions
- Provide an explicit owner type when constructing the parameterized type, e.g. new ParameterizedTypeImpl(ownerType, rawType, args).
- Make the nested class static (preferred) so no owner is required: add the `static` modifier to the inner class.
- Restructure the model so nested types are top-level or static nested classes when you do not need the enclosing instance.
Example fix
// before
class Outer { class Inner<T> {} }
Type t = TypeToken.getParameterized(Outer.Inner.class, String.class).getType(); // throws
// after (option A: static)
class Outer { static class Inner<T> {} }
// after (option B: give owner)
Type t = new ParameterizedTypeImpl(Outer.class, Outer.Inner.class, String.class).getType(); Defensive patterns
Strategy: validation
Validate before calling
boolean needsOwner(Class<?> raw) {
return !Modifier.isStatic(raw.getModifiers()) && raw.getDeclaringClass() != null;
}
// before building: if (needsOwner(raw) && owner == null) owner = raw.getDeclaringClass(); Type guard
static boolean requiresOwner(Class<?> c) {
return com.google.gson.internal.GsonTypes.requiresOwnerType(c);
} Prevention
- Make nested types static by default; only use inner classes when you need the enclosing instance.
- When constructing parameterized types programmatically, check requiresOwnerType and supply an owner.
- Document the owner requirement on any non-static nested generic type you expose.
When it happens
Trigger: Calling TypeToken.getParameterized(InnerNonStaticClass.class, ...) or otherwise constructing a ParameterizedTypeImpl where rawType has a non-null declaring class and lacks the static modifier, with ownerType == null (GsonTypes.java:522).
Common situations: Modeling JSON onto non-static inner classes; refactoring a static nested class to a (non-static) inner class and forgetting to add a TypeToken owner; reflecting on thread-state or context objects that nest as inner classes.
Related errors
- Primitive type is not allowed
- At most one lower bound is supported
- Exactly one upper bound must be specified
- Must only create direct subclasses of TypeToken
- Raw type is not supported because it requires specifying an…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/8d49f0c734711801.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/GsonTypes.java:523
Class<?> rawTypeAsClass = (Class<?>) rawType;
return !Modifier.isStatic(rawTypeAsClass.getModifiers())
&& rawTypeAsClass.getDeclaringClass() != null;
}
return false;
}
private static final class ParameterizedTypeImpl implements ParameterizedType {
private final Type ownerType;
private final Type rawType;
private final Type[] typeArguments;
ParameterizedTypeImpl(Type ownerType, Class<?> rawType, Type... typeArguments) {
requireNonNull(rawType);
if (ownerType == null && requiresOwnerType(rawType)) {
throw new IllegalArgumentException("Must specify owner type for " + rawType);
}
this.ownerType = ownerType == null ? null : canonicalize(ownerType);
this.rawType = canonicalize(rawType);
this.typeArguments = typeArguments.clone();
for (int t = 0, length = this.typeArguments.length; t < length; t++) {
requireNonNull(this.typeArguments[t]);
checkNotPrimitive(this.typeArguments[t]);
this.typeArguments[t] = canonicalize(this.typeArguments[t]);
}
}
@Override
public Type[] getActualTypeArguments() {
return typeArguments.clone();
}
@OverrideView on GitHub (pinned to 310ac341f2)