mybatis/mybatis-3 · error · ExecutorException
Error preparing statement. Cause: {}
Error message
Error preparing statement. Cause: {} What it means
A non-SQLException error occurred while preparing a java.sql.Statement: instantiateStatement(connection) plus timeout/fetch-size setup is wrapped, and any failure other than a raw SQLException (which is rethrown as-is) is wrapped as 'Error preparing statement' with the cause. Typical causes are illegal/unsupported timeout or fetch-size values, driver runtime errors, or reflection-style failures inside the driver.
Source
Thrown at src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java:99
public ParameterHandler getParameterHandler() {
return parameterHandler;
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
statement = instantiateStatement(connection);
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
Integer queryTimeout = null;
if (mappedStatement.getTimeout() != null) {
queryTimeout = mappedStatement.getTimeout();
} else if (configuration.getDefaultStatementTimeout() != null) {
queryTimeout = configuration.getDefaultStatementTimeout();
}
if (queryTimeout != null) {
stmt.setQueryTimeout(queryTimeout);
}
StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
}
View on GitHub (pinned to 008069adb1)
Solutions
- Read the cause exception — it names the actual failing call (usually setQueryTimeout or setFetchSize with an invalid value).
- Fix or remove the invalid timeout/fetchSize on the statement and Configuration defaults.
- Upgrade or replace the JDBC driver if it throws non-SQLException errors on legal values.
- Verify the SQL string itself against the driver (prepare-time syntax checks surface here as SQLException with the SQL bound into ErrorContext).
Example fix
<!-- before --> <settings> <setting name="defaultStatementTimeout" value="-1"/> </settings> <!-- after --> <settings> <setting name="defaultStatementTimeout" value="30"/> </settings>
Defensive patterns
Strategy: try-catch
Validate before calling
// validate timeout/fetchSize settings before building the SqlSessionFactory
int timeout = configuration.getDefaultStatementTimeout() == null
? 0 : configuration.getDefaultStatementTimeout();
if (timeout < 0) throw new IllegalStateException("defaultStatementTimeout must be >= 0");
if (configuration.getDefaultFetchSize() != null && configuration.getDefaultFetchSize() <= 0
&& !configuration.getDefaultFetchSize().equals(Integer.MIN_VALUE)) {
throw new IllegalStateException("defaultFetchSize must be positive (or Integer.MIN_VALUE for streaming)");
} Try / catch
try {
return session.selectList("stmt");
} catch (PersistenceException e) {
if (e.getMessage() != null && e.getMessage().contains("Error preparing statement")) {
// inspect cause: invalid timeout/fetchSize or driver prepare failure; report SQL from ErrorContext
log.error("Prepare failed for sql={} cause={}", org.apache.ibatis.executor.ErrorContext.instance().getSql(), e.getCause());
}
throw e;
} Prevention
- Validate statement timeout/fetchSize values (positive ints) in config at startup.
- Exercise one representative query per datasource in a health check so driver prepare problems surface before traffic.
When it happens
Trigger: Calling executor/statementHandler.prepare(...) — i.e. executing any mapped statement — where setting timeout (mappedStatement.getTimeout() or defaultStatementTimeout) or fetchSize throws a RuntimeException/Error, or the driver raises a non-SQLException during PreparedStatement creation.
Common situations: Setting timeout=-1 or another invalid value via <select timeout="..."> or defaultStatementTimeout; drivers that do not support setFetchSize values used (e.g. positive fetch size on MySQL without streaming); driver jar incompatibilities throwing runtime exceptions during prepare.
Related errors
- Cache-ref not yet resolved
- Could not find result map '{resultMapName}' referenced from
- Couldn't get a lock in {timeout} for the key {key} at the ca
- Error accessing PooledConnection. Connection is invalid.
- Error getting constructor collection nested result map value
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/db9be6ea1ab95ada.
Report an issue: GitHub.