mybatis/mybatis-3 · error · LogException
Error creating logger for logger
Error message
Error creating logger for logger {}. Cause: {} What it means
LogFactory.getLog(String) throws LogException when instantiating the selected Log implementation fails — logConstructor.newInstance(logger) threw. The constructor was resolved earlier by setImplementation(); failure at this point usually means the underlying logging library threw in its constructor or the class could not be initialized at runtime (missing dependency after repackaging, classloader isolation).
Solutions
- Check the chained cause — it names the exact class/init failure (NoClassDefFoundError, ClassNotFoundException, backend exception).
- Ensure the chosen logging backend jar (slf4j-api, log4j, etc.) is on the runtime classpath at the same classloader level as mybatis.
- Switch to a backend you actually ship, e.g. LogFactory.useSlf4jLogging() when only SLF4J is present, or useStdOutLogging() for isolated tests.
- In shaded jars, keep META-INF services and logging packages un-relocated or exclude them from shading.
Example fix
// before: backend classes missing at runtime LogFactory.useLog4J2Logging(); // resolves, then fails per-logger // after: force a backend you control LogFactory.useSlf4jLogging(); // slf4j-api is on the classpath
Defensive patterns
Strategy: try-catch
Validate before calling
// Probe the backend once at startup before any mapper work
try {
LogFactory.getLog("startup-probe");
} catch (LogException e) {
LogFactory.useStdOutLogging(); // known-good fallback for isolated environments
LogFactory.getLog("startup-probe");
} Try / catch
try {
log = LogFactory.getLogger(Xxx.class);
} catch (LogException e) {
// fall back to a logger you control; do not let logging kill initialization
log = internalStdOutLog;
} Prevention
- Pin exactly one logging backend in dependencies so adapter probing is deterministic.
- In shaded/OSGi deployments, verify the logging packages remain loadable by the same classloader as mybatis.
- Smoke-test LogFactory.getLog() during application startup, when falling back is still cheap.
When it happens
Trigger: Any first use of MyBatis logging (getLog called during mapper initialization) after a setImplementation/useSlf4jLogging-style call succeeded but the adapter's constructor (or static init of the underlying logger like Log4j2/Slf4j classes) fails in the deployment classloader.
Common situations: Application-server classloader hierarchies where the logging jar is visible to LogFactory but not instantiable; shaded/uber-jar builds stripping logging classes; OSGi deployments; logging backend throwing during initialization (misconfigured Log4j2 config).
Related errors
- Error setting driver on UnpooledDataSource.
- Error setting Log implementation. Cause
- Bad zip entry
- Cannot enable lazy loading because CGLIB is not available…
- Cannot enable lazy loading because Javassist is not…
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/cb1939583c75fe72.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/apache/ibatis/logging/LogFactory.java:56
tryImplementation(LogFactory::useLog4J2Logging);
tryImplementation(LogFactory::useLog4JLogging);
tryImplementation(LogFactory::useJdkLogging);
tryImplementation(LogFactory::useNoLogging);
}
private LogFactory() {
// disable construction
}
public static Log getLog(Class<?> clazz) {
return getLog(clazz.getName());
}
public static Log getLog(String logger) {
try {
return logConstructor.newInstance(logger);
} catch (Throwable t) {
throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t);
}
}
public static void useCustomLogging(Class<? extends Log> clazz) {
setImplementation(clazz);
}
public static void useSlf4jLogging() {
setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
}
public static void useCommonsLogging() {
setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
}
/**
* @deprecated Since 3.5.9 - See https://github.com/mybatis/mybatis-3/issues/1223. This method will remove future.
*/View on GitHub (pinned to 008069adb1)