google/gson · error · IllegalArgumentException
TypeToken captured `null` as type argument; probably a…
Error message
TypeToken captured `null` as type argument; probably a compiler / runtime bug
What it means
Thrown by TypeToken.verifyNoTypeVariable when a component of the captured type argument is null. This is a known JDK/Eclipse compiler quirk (see eclipse-jdt/eclipse.jdt.core#975, reproduced e.g. on Java 11.0.18) where capturing a type variable declared by a method of a local class yields null instead of a TypeVariable. The message explicitly attributes it to a compiler/runtime bug.
Solutions
- Build with javac instead of Eclipse ecj (or update Eclipse JDT to a version with the fix for eclipse.jdt.core#975).
- Update to a JDK point release that no longer exhibits the null-returning reflection bug.
- Refactor to avoid TypeToken capture inside local classes with generic methods; use TypeToken.getParameterized at runtime instead.
- If unavoidable, the system property gson.allowCapturingTypeVariables=true bypasses verifyNoTypeVariable entirely (accept the type-safety implications).
Example fix
// before (broken on affected Eclipse/JDK)
public void process() {
class Local {
<T> TypeToken<T> token() { return new TypeToken<T>() {}; } // null type var on buggy JVM
}
}
// after: avoid capture; use runtime construction
public void process(Class<?> type) {
TypeToken<?> token = TypeToken.get(type);
}
// build with javac instead of ecj, or update Eclipse JDT/JDK to a fixed release. Defensive patterns
Strategy: fallback
Validate before calling
// detect affected toolchain early; recommend build-system switch
System.out.println("javac/ecj: " + System.getProperty("java.vm.version"));
// prefer building with javac; in tests assert a known TypeToken resolves
TypeToken<?> probe = TypeToken.get(String.class);
if (probe == null) throw new IllegalStateException(); Try / catch
try {
return new TypeToken<T>() {}; // local class generic method on buggy JVM
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("TypeToken captured `null`")) {
// bypass verify by constructing at runtime
return TypeToken.get(elementType);
}
throw e;
} Prevention
- Build with javac rather than Eclipse ecj in CI/release pipelines.
- Keep JDK current; the underlying reflection bug is fixed in later point releases.
- Avoid constructing TypeTokens inside local classes with generic methods.
- Use TypeToken.get / getParameterized for runtime types.
When it happens
Trigger: Using the Eclipse JDT compiler (or an affected JDK like 11.0.18) and constructing a TypeToken inside a local class whose method declares a type variable that gets captured. The reflection API returns null where a TypeVariable was expected, tripping the `type == null` branch.
Common situations: Eclipse IDE builds producing class files that exhibit the null type-variable bug; specific JDK point releases (11.0.18) with the underlying reflection bug; local/anonymous classes with generic methods; switching between javac and ecj producing different runtime behavior.
Related errors
- rawType must be of type Class, but was
- TypeToken type argument must not contain a type variable…
- Must only create direct subclasses of TypeToken
- Must specify owner type for
- Primitive type is not allowed
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/cd1bce9ec511de39.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/reflect/TypeToken.java:155
verifyNoTypeVariable(ownerType);
}
for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
verifyNoTypeVariable(typeArgument);
}
} else if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
for (Type bound : wildcardType.getLowerBounds()) {
verifyNoTypeVariable(bound);
}
for (Type bound : wildcardType.getUpperBounds()) {
verifyNoTypeVariable(bound);
}
} else if (type == null) {
// Occurs in Eclipse IDE and certain Java versions (e.g. Java 11.0.18) when capturing type
// variable declared by method of local class, see
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/975
throw new IllegalArgumentException(
"TypeToken captured `null` as type argument; probably a compiler / runtime bug");
}
}
/** Returns the raw (non-generic) type for this type. */
public final Class<? super T> getRawType() {
return rawType;
}
/** Gets underlying {@code Type} instance. */
public final Type getType() {
return type;
}
/**
* Check if this type is assignable from the given class object.
*
* @deprecated this implementation may be inconsistent with javac for types with wildcards.View on GitHub (pinned to 310ac341f2)