mybatis/mybatis-3 · error · TypeException
'{}' extends TypeReference but misses the type parameter. Re
Error message
'{}' extends TypeReference but misses the type parameter. Remove the extension or add a type parameter to it. What it means
TypeReference captures its generic type by walking the superclass chain to find a ParameterizedType. If the chain bottoms out at TypeReference itself without ever passing through a parameterized declaration (a raw subclass like 'class Foo extends TypeReference'), the type argument cannot be captured and this TypeException names the offending class.
Source
Thrown at src/main/java/org/apache/ibatis/type/TypeReference.java:47
* @author Simone Tripodi
*/
public abstract class TypeReference<T> {
private final Type rawType;
protected TypeReference() {
rawType = getSuperclassTypeParameter(getClass());
}
Type getSuperclassTypeParameter(Class<?> clazz) {
Type genericSuperclass = clazz.getGenericSuperclass();
if (genericSuperclass instanceof Class) {
// try to climb up the hierarchy until meet something useful
if (TypeReference.class != genericSuperclass) {
return getSuperclassTypeParameter(clazz.getSuperclass());
}
throw new TypeException("'" + getClass() + "' extends TypeReference but misses the type parameter. "
+ "Remove the extension or add a type parameter to it.");
}
return ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
}
public final Type getRawType() {
return rawType;
}
@Override
public String toString() {
return rawType.toString();
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Add the type parameter: class MyHandler extends TypeReference<String>
- Parameterize every intermediate class in the hierarchy, not just the leaf
- If the base extension is accidental (you did not need TypeReference), remove it and implement TypeHandler directly
Example fix
// before
public class IdRef extends TypeReference { } // raw
// after
public class IdRef extends TypeReference<Long> { } Defensive patterns
Strategy: validation
Validate before calling
void checkTypeReference(Class<?> c) {
Type sup = c.getGenericSuperclass();
if (sup instanceof Class && sup == TypeReference.class) {
throw new IllegalStateException(c.getName() + " extends TypeReference raw — add a type parameter");
}
} Type guard
static boolean isParameterizedTypeReference(Class<?> c) {
return c.getGenericSuperclass() instanceof ParameterizedType;
} Prevention
- Never extend TypeReference raw — always supply <T>
- Parameterize every intermediate class in handler hierarchies
- Enable -Xlint:raw-types and treat raw-type warnings as errors in handler code
When it happens
Trigger: Declaring a raw subclass: class MyHandler extends TypeReference (no <T>); extending a raw intermediate class (class Middle extends TypeReference, then class MyHandler extends Middle); using the handler in a mapper before any type info is resolvable.
Common situations: Copy-pasting BaseTypeHandler subclasses that extend TypeReference-backed bases without adding the type parameter; legacy pre-generics code compiled with raw types after a library upgrade introduced TypeReference.
Related errors
- Type {typeHandlerType} is not a valid TypeHandler because it
- SqlRunner could not find a TypeHandler instance for {}
- The 2nd arg must be Class or ParameterizedType, but was: {}
- '" + this.getClass() + "' must override the default method '
- '" + this.getClass() + "' must override the default method '
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/22755954dee2d4ae.
Report an issue: GitHub.