baomidou/mybatis-plus · error · ClassNotFoundException
Cannot find class: {}
Error message
Cannot find class: {} What it means
ClassUtils.loadClass iterates every supplied ClassLoader and calls Class.forName(className, true, classLoader). If none of them can resolve the class, a ClassNotFoundException with the message 'Cannot find class: <name>' is thrown. This is the terminal failure of mybatis-plus's class resolution utility, used when the framework reflectively loads classes named in configuration (e.g. type handlers, entity classes, interceptors).
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ClassUtils.java:185
public static Class<?> toClassConfident(String name, ClassLoader classLoader) {
try {
return loadClass(name, getClassLoaders(classLoader));
} catch (ClassNotFoundException e) {
throw ExceptionUtils.mpe("找不到指定的class!请仅在明确确定会有 class 的时候,调用该方法", e);
}
}
private static Class<?> loadClass(String className, ClassLoader[] classLoaders) throws ClassNotFoundException {
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
try {
return Class.forName(className, true, classLoader);
} catch (ClassNotFoundException e) {
// ignore
}
}
}
throw new ClassNotFoundException("Cannot find class: " + className);
}
/**
* Determine the name of the package of the given class,
* e.g. "java.lang" for the {@code java.lang.String} class.
*
* @param clazz the class
* @return the package name, or the empty String if the class
* is defined in the default package
*/
public static String getPackageName(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
return getPackageName(clazz.getName());
}
/**
* Determine the name of the package of the given fully-qualified class name,View on GitHub (pinned to bf67d90747)
Solutions
- Verify the fully-qualified class name string is spelled correctly and matches the actual package (watch out for shading/relocation prefixes).
- Confirm the jar containing the class is on the runtime classpath of the module that performs the reflective load.
- In container/classloader-mismatch situations, set Thread.currentThread().setContextClassLoader(targetClassLoader) before the mybatis-plus call so the context loader can resolve the class.
- Reproduce with Class.forName(name) in the same deployment to prove it is a classpath/classloader problem and not a mybatis-plus bug.
Example fix
// before: class only visible to app classloader, context loader misses it String name = "com.acme.biz.CustomTypeHandler"; Class<?> clazz = ClassUtils.toClassConfident(name); // ClassNotFoundException // after: align the context classloader before resolution Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Class<?> clazz = ClassUtils.toClassConfident(name);
Defensive patterns
Strategy: validation
Validate before calling
String name = "com.acme.biz.Thing";
boolean resolvable;
try {
Class.forName(name, true, Thread.currentThread().getContextClassLoader());
resolvable = true;
} catch (ClassNotFoundException e) {
resolvable = false;
}
if (!resolvable) { /* fix classpath/classloader before proceeding */ } Try / catch
try {
Class<?> clazz = ClassUtils.toClassConfident(name);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Class not on runtime classpath: " + name
+ " — check dependencies and context classloader", e);
} Prevention
- Validate configured class names at startup (fail fast with a clear message) instead of lazily during a request.
- In embedded/container setups, set the context classloader explicitly before mybatis-plus initializes.
- Pin and verify dependencies so reflective targets cannot disappear during upgrades or shading.
When it happens
Trigger: Calling ClassUtils.toClassConfident(name) / loadClass with a fully-qualified class name that is not on any of the candidate classloaders (context classloader, ClassUtils's own classloader). Typical entry points: specifying a nonexistent className in mybatis-plus configuration, entity scanning resolving a class name built from a table name, or running in an environment (OSGi, war on some servers, fat-jar relocations) where the context classloader cannot see application classes.
Common situations: Typos in configured class names; shaded/relocated jars where the package prefix changed; complex containers (Tomcat war deployment, Spring Boot executable jar with custom launcher) where Thread.currentThread().getContextClassLoader() differs from the classloader that loaded mybatis-plus; missing dependency on the classpath.
Related errors
- Failed to create a new Configuration instance.
- Failed invoking constructor for handler {}
- Unable to get MybatisMapperProxy : {}
- Failed to extract Groovy lambda meta from proxy handler: {}
- %s already contains value for %s
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/6a6ba8f01fe221f3.
Report an issue: GitHub.