google/gson · error · IllegalArgumentException

{contextRawType} is not the same as or a subtype of {superty

Error message

{contextRawType} is not the same as or a subtype of {supertype}

What it means

GsonTypes.getSupertype asserts that the supplied supertype is actually assignable from the context's raw type; otherwise it throws IllegalArgumentException. It is an internal invariant violation in generic-supertype resolution — the caller claimed a supertype relationship that does not hold.

Source

Thrown at gson/src/main/java/com/google/gson/internal/GsonTypes.java:288

  /**
   * Returns the generic form of {@code supertype}. For example, if this is {@code
   * ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
   * Iterable.class}.
   *
   * @param supertype a superclass of, or interface implemented by, this.
   */
  private static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype) {
    if (context instanceof WildcardType) {
      // Wildcards are useless for resolving supertypes. As the upper bound has the same raw type,
      // use it instead
      Type[] bounds = ((WildcardType) context).getUpperBounds();
      // Currently the JLS only permits one bound for wildcards so using first bound is safe
      assert bounds.length == 1;
      context = bounds[0];
    }
    if (!supertype.isAssignableFrom(contextRawType)) {
      throw new IllegalArgumentException(
          contextRawType + " is not the same as or a subtype of " + supertype);
    }
    return resolve(
        context, contextRawType, GsonTypes.getGenericSupertype(context, contextRawType, supertype));
  }

  /**
   * Returns the component type of this array type.
   *
   * @throws ClassCastException if this type is not an array.
   */
  public static Type getArrayComponentType(Type array) {
    return array instanceof GenericArrayType
        ? ((GenericArrayType) array).getGenericComponentType()
        : ((Class<?>) array).getComponentType();
  }

  /**

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Verify the supertype argument: ensure supertype.isAssignableFrom(rawType) before calling getSupertype.
  2. Fix the TypeAdapterFactory to use the correct supertype from getGenericSuperclass()/getGenericInterfaces().
  3. Add a unit test asserting the hierarchy assumption holds for the target types.
  4. Avoid reflecting across unrelated class hierarchies in custom adapters.

Example fix

// before
Type t = GsonTypes.getSupertype(context, Dog.class, Vehicle.class); // Dog !<: Vehicle

// after
Type t = GsonTypes.getSupertype(context, Dog.class, Animal.class); // Dog <: Animal
Defensive patterns

Strategy: validation

Validate before calling

if (!supertype.isAssignableFrom(rawType)) {
  throw new IllegalArgumentException(rawType + " not a " + supertype);
}

Type guard

boolean isSupertypeOf(Class<?> rawType, Class<?> supertype) {
  return supertype.isAssignableFrom(rawType);
}

Try / catch

try {
  return GsonTypes.getSupertype(context, rawType, supertype);
} catch (IllegalArgumentException ex) {
  // pick the correct superclass/interface from rawType.getGenericSuperclass()/getGenericInterfaces()
  throw ex;
}

Prevention

When it happens

Trigger: Custom TypeAdapterFactory / InstanceCreator invoking reflection helpers with an incorrect supertype/class pairing; programmatic TypeToken.getSupertype() with a class that is not a superclass/interface; bytecode/manipulation producing inconsistent Type metadata.

Common situations: Bugs in user-written TypeAdapterFactories; refactoring a class hierarchy without updating TypeToken supertype calls; proxy/AOP frameworks altering class metadata; misconfigured generic hierarchies.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/2407f73e1c8cc08f.json. Report an issue: GitHub.