google/gson · error · JsonIOException
Invalid EnumMap type
Error message
Invalid EnumMap type: ${type} What it means
Thrown when Gson constructs an EnumMap whose type is a ParameterizedType but the key type argument is not a concrete Class (e.g. a TypeVariable). EnumMap's constructor requires a concrete enum class for the key. Only raw EnumMap (not subclasses) is supported. The message includes the type.
Solutions
- Use a concrete TypeToken<EnumMap<MyEnum, String>> when deserializing
- Register an InstanceCreator<EnumMap> returning new EnumMap<>(MyEnum.class)
- Register a TypeAdapter for the wrapper that handles EnumMap construction
Example fix
// before - K unresolved
class Wrapper<K extends Enum<K>, V> { EnumMap<K, V> map; }
// after - register InstanceCreator
gsonBuilder.registerTypeAdapter(EnumMap.class,
(InstanceCreator<EnumMap>) type -> new EnumMap<>(MyEnum.class)); Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure EnumMap key type is a concrete Class before deserializing
Type targetType = typeToken.getType();
if (targetType instanceof ParameterizedType) {
Type keyType = ((ParameterizedType) targetType).getActualTypeArguments()[0];
if (!(keyType instanceof Class)) {
throw new IllegalStateException("EnumMap key type must be concrete Class, got " + keyType);
}
} Type guard
static boolean isConcreteEnumMap(Type type) {
if (!(type instanceof ParameterizedType)) return false;
ParameterizedType pt = (ParameterizedType) type;
if (pt.getRawType() != EnumMap.class) return false;
return pt.getActualTypeArguments()[0] instanceof Class
&& ((Class<?>) pt.getActualTypeArguments()[0]).isEnum();
} Prevention
- Always use concrete TypeToken<EnumMap<MyEnum, V>> when deserializing EnumMap
- Register an InstanceCreator<EnumMap> if the key type can't be resolved at runtime
- Note: only raw EnumMap (not subclasses) is supported by Gson's special constructor
When it happens
Trigger: Deserializing EnumMap<K, V> where K is an unresolved type variable; a generic wrapper with an EnumMap<K, V> field where the key cannot be resolved to a concrete enum class.
Common situations: Generic container classes with EnumMap<K,V> fields; type parameters that can't be resolved through the type hierarchy.
Related errors
- Invalid EnumSet type
- Failed to invoke constructor
- Array must have size 1, but has size
- At most one lower bound is supported
- Attempted to deserialize a java.lang.Class. Forgot to…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/5a93f0e9239af470.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java:206
throw new JsonIOException("Invalid EnumSet type: " + type);
}
} else {
throw new JsonIOException("Invalid EnumSet type: " + type);
}
};
}
// Only support creation of EnumMap, but not of custom subtypes; for them type parameters
// and constructor parameter might have completely different meaning
else if (rawType == EnumMap.class) {
return () -> {
if (type instanceof ParameterizedType) {
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
if (elementType instanceof Class) {
@SuppressWarnings({"unchecked", "rawtypes"})
T map = (T) new EnumMap((Class) elementType);
return map;
} else {
throw new JsonIOException("Invalid EnumMap type: " + type);
}
} else {
throw new JsonIOException("Invalid EnumMap type: " + type);
}
};
}
return null;
}
private static <T> ObjectConstructor<T> newDefaultConstructor(
Class<? super T> rawType, FilterResult filterResult) {
// Cannot invoke constructor of abstract class
if (Modifier.isAbstract(rawType.getModifiers())) {
return null;
}
Constructor<? super T> constructor;View on GitHub (pinned to 310ac341f2)