baomidou/mybatis-plus · error · TypeException
Failed invoking constructor for handler {}
Error message
Failed invoking constructor for handler {} What it means
MybatisUtils' type-handler factory instantiates an IJsonTypeHandler. It first tries the constructor (Class, Field); if no Field is available it falls back to the (Class) constructor. If that reflective instantiation throws (wrong constructor signature, abstract class, inaccessible constructor, or constructor itself failing), it is wrapped in a MyBatis TypeException: 'Failed invoking constructor for handler <type>'.
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java:97
* @param javaTypeClass java类型信息
* @param field 属性字段
* @return 实例化类型处理器
*/
public static TypeHandler<?> newJsonTypeHandler(Class<? extends TypeHandler<?>> typeHandler, Class<?> javaTypeClass, Field field) {
TypeHandler<?> result = null;
if (IJsonTypeHandler.class.isAssignableFrom(typeHandler)) {
if (field != null) {
try {
result = typeHandler.getConstructor(Class.class, Field.class).newInstance(javaTypeClass, field);
} catch (ReflectiveOperationException e) {
// ignore
}
}
if (result == null) {
try {
result = typeHandler.getConstructor(Class.class).newInstance(javaTypeClass);
} catch (ReflectiveOperationException ex) {
throw new TypeException("Failed invoking constructor for handler " + typeHandler, ex);
}
}
}
return result;
}
/**
* 获取SqlSessionFactory
* <p>当自定义实现{@link SqlSession}时,请实现对{@link SqlSessionFactory}的访问 (spring的方式)</p>
* <p>当无法获得{@link SqlSessionFactory}时,需要将{@link SqlSessionFactory}绑定至上下文对象中(原生mybatis访问方式)</p>
*
* @param mybatisMapperProxy {@link MybatisMapperProxy}
* @return SqlSessionFactory
* @see DefaultSqlSession
* @see GlobalConfigUtils#getGlobalConfig(Configuration)
* @see GlobalConfigUtils#setGlobalConfig(Configuration, GlobalConfig)
* @since 3.5.7
*/View on GitHub (pinned to bf67d90747)
Solutions
- Give the handler a public constructor accepting (Class javaType) and, for field-level instantiation, public (Class javaType, Field field).
- Ensure the class is concrete (not abstract/interface) and the constructors are public.
- If the constructor body throws, check its cause chain (ex) — commonly a missing JSON dependency (jackson-databank / fastjson) that must be added to the classpath.
- Verify the javaType class passed in is loadable and non-null in the type handler registration.
Example fix
// before: incompatible constructor -> TypeException
public class JsonTypeHandler extends BaseTypeHandler<MyBean> {
public JsonTypeHandler(Field field) { ... }
}
// after: provide the expected (Class) constructor (and optionally (Class, Field))
public class JsonTypeHandler extends BaseTypeHandler<MyBean> {
public JsonTypeHandler(Class<?> type) {
super();
this.type = Objects.requireNonNull(type);
}
public JsonTypeHandler(Class<?> type, Field field) {
this(type);
this.field = field;
}
} Defensive patterns
Strategy: validation
Validate before calling
Class<? extends TypeHandler<?>> h = MyHandler.class;
boolean hasClassCtor = false;
for (Constructor<?> c : h.getConstructors()) {
Class<?>[] p = c.getParameterTypes();
if (p.length == 1 && p[0] == Class.class) hasClassCtor = true;
}
if (!hasClassCtor) throw new IllegalStateException(h + " needs a public (Class) constructor"); Type guard
static boolean isInstantiableJsonHandler(Class<?> t) {
return IJsonTypeHandler.class.isAssignableFrom(t)
&& !t.isInterface() && !java.lang.reflect.Modifier.isAbstract(t.getModifiers());
} Try / catch
try {
TypeHandler<?> th = newGeneratorInstance(handlerClass, javaType);
} catch (TypeException e) {
throw new IllegalStateException("Handler " + handlerClass.getName()
+ " must expose public (Class[, Field]) constructors; root cause: " + e.getCause(), e);
} Prevention
- Standardize custom JSON handlers on public (Class javaType) and (Class, Field) constructors.
- Add a startup smoke test that instantiates each registered handler once.
When it happens
Trigger: Configuring a custom type handler implementing IJsonTypeHandler whose only constructors do not match (Class, Field) or (Class) — e.g. one that takes only a Field, takes (Class, String), or has only a no-arg constructor with a non-public modifier. It also fires when the matched constructor exists but throws (missing JSON library on classpath, null javaType).
Common situations: Upgrading mybatis-plus versions where the expected handler constructor shape changed; writing a Jackson/Fastjson type handler with a non-standard constructor; deploying a custom handler whose constructor calls a dependency that is not wired.
Related errors
- Failed to create a new Configuration instance.
- Failed invoking constructor for handler %s
- Unable to find a usable constructor for %s
- Cannot find class: {}
- Unable to get MybatisMapperProxy : {}
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/ec82747b9c073e57.
Report an issue: GitHub.