mybatis/mybatis-3 · error · TypeException
Failed to invoke constructor for handler {}
Error message
Failed to invoke constructor for handler {} What it means
The companion of error 257: a usable constructor was FOUND but invoking it failed with a ReflectiveOperationException other than NoSuchMethodException — typically an exception thrown inside the no-arg constructor, or instantiation of an abstract/classloader-hidden class. The handler class name is included in the message.
Source
Thrown at src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java:534
return (TypeHandler<T>) c.newInstance(javaType);
} catch (NoSuchMethodException ignored) {
}
if (javaType instanceof Class) {
try {
c = handlerClass.getConstructor(Class.class);
return (TypeHandler<T>) c.newInstance(javaType);
} catch (NoSuchMethodException ignored) {
}
}
}
try {
c = handlerClass.getConstructor();
return (TypeHandler<T>) c.newInstance();
} catch (NoSuchMethodException e) {
throw new TypeException("Unable to find a usable constructor for " + handlerClass, e);
}
} catch (ReflectiveOperationException e) {
throw new TypeException("Failed to invoke constructor for handler " + handlerClass, e);
}
}
// scan
public void register(String packageName) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
for (Class<?> type : handlerSet) {
// Ignore inner classes and interfaces (including package-info.java) and abstract classes
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
register(type);
}
}
}
// get informationView on GitHub (pinned to 008069adb1)
Solutions
- Check the Cause — if it is your own exception, move that initialization out of the constructor or make it safe
- Ensure the handler class is public, concrete, and visible to MyBatis' classloader
- Initialize expensive state lazily (on first set/get) instead of in the constructor
Example fix
// before
public MyHandler() { this.cfg = Files.readString(Path.of("/etc/app.cfg")); } // throws in prod
// after
public MyHandler() { }
private Config cfg() { return ConfigHolder.INSTANCE; } // lazy Defensive patterns
Strategy: try-catch
Validate before calling
try {
Object h = handlerClass.getDeclaredConstructor().newInstance(); // dry-run at registration time
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Handler constructor failed: " + handlerClass, e);
} Try / catch
try { registry.getInstance(type, handlerClass); } catch (TypeException e) { Throwable c = e.getCause(); // constructor body failed: inspect c and fix initialization } Prevention
- Keep constructors trivial; defer resource loading to first use
- Fail fast at boot by eagerly instantiating all registered handlers
When it happens
Trigger: A no-arg constructor that performs initialization (loading config, opening resources) and throws; handler class loaded by a different classloader triggering IllegalAccess; accidentally referencing an abstract handler class.
Common situations: Handlers that read properties/registries in their constructor; fat-jar or container classloader setups; constructor logic that depends on environment (files, env vars) absent in the current deployment.
Related errors
- Unable to find a usable constructor for {}
- Type {typeHandlerType} is not a valid TypeHandler because it
- Cannot get Configuration as factory method [" + this.configu
- @AutomapConstructor should be used in only one constructor.
- SqlRunner could not find a TypeHandler instance for {}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/965713bf95f07152.
Report an issue: GitHub.