{"record":{"id":"db9be6ea1ab95ada","repo":"mybatis/mybatis-3","slug":"error-preparing-statement-cause","errorCode":null,"errorMessage":"Error preparing statement.  Cause: {}","messagePattern":"Error preparing statement\\.  Cause: (.+?)","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java","lineNumber":99,"sourceCode":"  public ParameterHandler getParameterHandler() {\n    return parameterHandler;\n  }\n\n  @Override\n  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {\n    ErrorContext.instance().sql(boundSql.getSql());\n    Statement statement = null;\n    try {\n      statement = instantiateStatement(connection);\n      setStatementTimeout(statement, transactionTimeout);\n      setFetchSize(statement);\n      return statement;\n    } catch (SQLException e) {\n      closeStatement(statement);\n      throw e;\n    } catch (Exception e) {\n      closeStatement(statement);\n      throw new ExecutorException(\"Error preparing statement.  Cause: \" + e, e);\n    }\n  }\n\n  protected abstract Statement instantiateStatement(Connection connection) throws SQLException;\n\n  protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {\n    Integer queryTimeout = null;\n    if (mappedStatement.getTimeout() != null) {\n      queryTimeout = mappedStatement.getTimeout();\n    } else if (configuration.getDefaultStatementTimeout() != null) {\n      queryTimeout = configuration.getDefaultStatementTimeout();\n    }\n    if (queryTimeout != null) {\n      stmt.setQueryTimeout(queryTimeout);\n    }\n    StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);\n  }\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java#L81-L117","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"<!-- before -->\n<settings>\n  <setting name=\"defaultStatementTimeout\" value=\"-1\"/>\n</settings>\n\n<!-- after -->\n<settings>\n  <setting name=\"defaultStatementTimeout\" value=\"30\"/>\n</settings>","handlingStrategy":"try-catch","validationCode":"// validate timeout/fetchSize settings before building the SqlSessionFactory\nint timeout = configuration.getDefaultStatementTimeout() == null\n    ? 0 : configuration.getDefaultStatementTimeout();\nif (timeout < 0) throw new IllegalStateException(\"defaultStatementTimeout must be >= 0\");\nif (configuration.getDefaultFetchSize() != null && configuration.getDefaultFetchSize() <= 0\n    && !configuration.getDefaultFetchSize().equals(Integer.MIN_VALUE)) {\n  throw new IllegalStateException(\"defaultFetchSize must be positive (or Integer.MIN_VALUE for streaming)\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return session.selectList(\"stmt\");\n} catch (PersistenceException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Error preparing statement\")) {\n    // inspect cause: invalid timeout/fetchSize or driver prepare failure; report SQL from ErrorContext\n    log.error(\"Prepare failed for sql={} cause={}\", org.apache.ibatis.executor.ErrorContext.instance().getSql(), e.getCause());\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["mybatis","jdbc","statement","timeout","fetch-size"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}