google/gson · error · IllegalStateException
TypeToken must be created with a type argument: new…
Error message
TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved.
See {} What it means
Thrown by TypeToken's protected constructor when the anonymous subclass's generic superclass is the RAW TypeToken class (no type argument supplied) rather than ParameterizedType<TypeToken<...>>. Gson cannot recover the missing type argument. The message explicitly calls out code shrinkers (ProGuard/R8) that strip generic signatures as a common cause.
Solutions
- If using ProGuard/R8, add `-keepattributes Signature` (and typically `*Annotation*`, `InnerClasses`) to your rules; for R8 this is usually inherited from the default Android rules but verify.
- Ensure TypeToken is instantiated as an anonymous subclass with an explicit type argument: `new TypeToken<List<String>>() {}` (note the empty `{}`).
- If a type argument is only known at runtime, use TypeToken.getParameterized(...) instead of an anonymous subclass.
- Update Gson and the Android Gradle Plugin; old AGP/Gson combinations occasionally drop signatures.
Example fix
// before (broken)
TypeToken<?> t = new TypeToken(){}; // raw, no type argument
// or ProGuard stripped signature from:
TypeToken<List<String>> t = new TypeToken<List<String>>(){};
// after (code fix)
TypeToken<List<String>> t = new TypeToken<List<String>>() {};
// after (ProGuard fix in proguard-rules.pro):
-keepattributes Signature, InnerClasses, EnclosingMethod
-keep class com.google.gson.reflect.TypeToken
-keep class * extends com.google.gson.reflect.TypeToken
// after (runtime-known type):
TypeToken<?> t = TypeToken.getParameterized(List.class, String.class); Defensive patterns
Strategy: validation
Validate before calling
// at app startup, verify generic signatures survive shrinking
TypeToken<List<String>> t = new TypeToken<List<String>>() {};
if (t.getType() instanceof Class) { // raw TypeToken, signature stripped
throw new IllegalStateException("Generic signatures stripped; add -keepattributes Signature");
} Type guard
public static boolean typeTokenResolved(TypeToken<?> t) {
return !(t.getType() instanceof Class) || ((Class<?>) t.getType()).getTypeParameters().length == 0 && t.getType() != TypeToken.class;
} Try / catch
try {
TypeToken<List<String>> t = new TypeToken<List<String>>() {};
return gson.fromJson(json, t.getType());
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("TypeToken must be created with a type argument")) {
throw new IllegalStateException("ProGuard/R8 stripped signatures; add -keepattributes Signature", e);
}
throw e;
} Prevention
- Add `-keepattributes Signature,InnerClasses,EnclosingMethod` to ProGuard/R8 rules.
- Add a startup assertion that a known TypeToken resolves to a ParameterizedType.
- Prefer TypeToken.getParameterized for runtime-known types.
- Test release/obfuscated builds with a TypeToken round-trip, not just debug builds.
When it happens
Trigger: Writing `new TypeToken(){}` (no <...>), or a properly-written `new TypeToken<List<String>>(){}` whose generic signature was stripped at build time by ProGuard/R8 without -keepattributes Signature. Also possible when reflection over the class file does not return ParameterizedType due to compiler bugs.
Common situations: Android release builds with ProGuard/R8 missing Signature attribute retention; copying TypeToken usage without the empty anonymous-class body or without the type argument; obfuscation configs that strip Signature/InnerClasses; some older Android Gradle Plugin defaults.
Related errors
- Must only create direct subclasses of TypeToken
- Must specify owner type for
- Primitive type is not allowed
- rawType must be of type Class, but was
- TypeToken captured `null` as type argument; probably a…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/6bd2dcb69af2142c.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/reflect/TypeToken.java:110
* Verifies that {@code this} is an instance of a direct subclass of TypeToken and returns the
* type argument for {@code T} in {@link GsonTypes#canonicalize canonical form}.
*/
private Type getTypeTokenTypeArgument() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
ParameterizedType parameterized = (ParameterizedType) superclass;
if (parameterized.getRawType() == TypeToken.class) {
Type typeArgument = GsonTypes.canonicalize(parameterized.getActualTypeArguments()[0]);
if (isCapturingTypeVariablesForbidden()) {
verifyNoTypeVariable(typeArgument);
}
return typeArgument;
}
}
// Check for raw TypeToken as superclass
else if (superclass == TypeToken.class) {
throw new IllegalStateException(
"TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code"
+ " shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved."
+ "\nSee "
+ TroubleshootingGuide.createUrl("type-token-raw"));
}
// User created subclass of subclass of TypeToken
throw new IllegalStateException("Must only create direct subclasses of TypeToken");
}
private static void verifyNoTypeVariable(Type type) {
if (type instanceof TypeVariable) {
TypeVariable<?> typeVariable = (TypeVariable<?>) type;
throw new IllegalArgumentException(
"TypeToken type argument must not contain a type variable; captured type variable "
+ typeVariable.getName()
+ " declared by "
+ typeVariable.getGenericDeclaration()View on GitHub (pinned to 310ac341f2)