mybatis/mybatis-3 · error · IllegalArgumentException
Parameter 'transactionFactory' must not be null
Error message
Parameter 'transactionFactory' must not be null
What it means
Environment's constructor throws IllegalArgumentException when transactionFactory is null. MyBatis needs a TransactionFactory (JdbcTransactionFactory or ManagedTransactionFactory) to open transactions for the environment, so it refuses null after the id check.
Source
Thrown at src/main/java/org/apache/ibatis/mapping/Environment.java:35
import javax.sql.DataSource;
import org.apache.ibatis.transaction.TransactionFactory;
/**
* @author Clinton Begin
*/
public final class Environment {
private final String id;
private final TransactionFactory transactionFactory;
private final DataSource dataSource;
public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
if (id == null) {
throw new IllegalArgumentException("Parameter 'id' must not be null");
}
if (transactionFactory == null) {
throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null");
}
this.id = id;
if (dataSource == null) {
throw new IllegalArgumentException("Parameter 'dataSource' must not be null");
}
this.transactionFactory = transactionFactory;
this.dataSource = dataSource;
}
public static class Builder {
private final String id;
private TransactionFactory transactionFactory;
private DataSource dataSource;
public Builder(String id) {
this.id = id;
}
View on GitHub (pinned to 008069adb1)
Solutions
- Pass a concrete factory: new JdbcTransactionFactory() (or ManagedTransactionFactory for container-managed transactions).
- If built by DI, verify the TransactionFactory bean exists and is injected.
- Add a null check earlier at the config-loading layer with a clearer message about which setting is missing.
Example fix
// before
Environment env = new Environment("dev", null, dataSource);
// after
Environment env = new Environment("dev", new JdbcTransactionFactory(), dataSource); Defensive patterns
Strategy: validation
Validate before calling
TransactionFactory txFactory = Objects.requireNonNull(txFactory, "TransactionFactory not wired");
new Environment("dev", txFactory, ds); Prevention
- Choose the factory deliberately: JdbcTransactionFactory for standalone apps, ManagedTransactionFactory in app servers.
- With DI, mark the TransactionFactory bean as required so wiring fails at startup with a clear error.
- Centralize Environment construction in one factory method instead of call sites.
When it happens
Trigger: new Environment("dev", null, dataSource) — typically the factory variable was never initialized or the wrong branch of a conditional left it null.
Common situations: Switching from XML to Java-based config and forgetting new JdbcTransactionFactory(); DI containers not wiring the field; copy-paste of an Environment construction with the factory argument dropped.
Related errors
- Parameter 'id' must not be null
- Parameter 'dataSource' must not be null
- ResultMaps must have an id
- dataSource cannot be null
- Invalid bound statement (not found): {mapperInterface}.{meth
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/58a6574b79183c68.
Report an issue: GitHub.