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

  1. Use a concrete TypeToken<EnumMap<MyEnum, String>> when deserializing
  2. Register an InstanceCreator<EnumMap> returning new EnumMap<>(MyEnum.class)
  3. 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

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


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)