dotnet/aspnetcore · error · RuntimeException

TypeReference must be instantiated with a type parameter…

Error message

TypeReference must be instantiated with a type parameter such as (new TypeReference<Foo<Bar>>() {}).

What it means

TypeReference<T> uses the super-type-token pattern: it captures T by reflecting the generic superclass of an anonymous subclass. If the subclass is not parameterized (e.g. 'new TypeReference()' with no <...>), getGenericSuperclass() is a Class, not a ParameterizedType, so the cast throws ClassCastException which is caught and rethrown as a RuntimeException with this message.

Solutions

  1. Always create TypeReference as an anonymous inner class WITH the type argument: new TypeReference<List<Integer>>() {}.
  2. Store the instance in a field typed with the parameter so the compiler keeps it: TypeReference<List<Integer>> listType = new TypeReference<List<Integer>>() {};.
  3. If you need a non-generic type, pass the Class directly (e.g. invoke(String.class, ...)) instead of TypeReference.

Example fix

// before
TypeReference ref = new TypeReference(); // raw -> throws

// after
TypeReference<List<Integer>> ref = new TypeReference<List<Integer>>() {};
Defensive patterns

Strategy: type-guard

Type guard

// Validate at construction that the subclass is parameterized.
public static <T> TypeReference<T> checked(TypeReference<T> ref) {
  if (ref.getType() == null) {
    throw new IllegalArgumentException("TypeReference missing type parameter");
  }
  return ref;
}

Try / catch

try {
  TypeReference<?> ref = new TypeReference() {}; // raw
} catch (RuntimeException e) {
  if (e.getMessage().contains("TypeReference must be instantiated")) {
    // guide developer to add the type parameter
  } else throw e;
}

Prevention

When it happens

Trigger: Instantiating 'new TypeReference()' (raw) instead of 'new TypeReference<Map<String,Integer>>() {}'. Also reached if someone subclasses TypeReference without specifying the type parameter.

Common situations: Copy-paste error omitting the generic; using TypeReference as a field of a non-parameterized class; refactor that lost the angle brackets; tooling/codegen that strips generics.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/06c30b65af07f1fe. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/TypeReference.java:40

     * spite of type erasure since, sadly, {@code Foo<Bar>.class} is not valid Java.
     *
     * To get the Type of Class {@code Foo<Bar>}, use the following syntax:
     * <pre>{@code
     * Type fooBarType = (new TypeReference<Foo<Bar>>() { }).getType();
     * }</pre>
     *
     * To get the Type of class Foo, use a regular Type Token:
     * <pre>{@code
     * Type fooType = Foo.class;
     * }</pre>
     *
     *  @see <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html">Super Type Tokens</a>
     */
    public TypeReference() {
        try {
            this.type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        } catch (ClassCastException ex) {
            throw new RuntimeException("TypeReference must be instantiated with a type parameter such as (new TypeReference<Foo<Bar>>() {}).");
        }
    }

    /**
     * Gets the referenced type.
     * @return The Type encapsulated by this TypeReference
     */
    public Type getType() {
        return this.type;
    }
}

View on GitHub (pinned to 3600ca084e)