mybatis/mybatis-3 · error · SqlSessionException

Error: Cannot get connection. No managed session is starte

Error message

Error:  Cannot get connection.  No managed session is started.

What it means

SqlSessionManager delegates session lifecycle methods to a thread-local SqlSession established by startManagedSession(). getConnection() checks localSqlSession; if no managed session was started on this thread it throws SqlSessionException 'Cannot get connection. No managed session is started.' It means you used the manager's manual/managed mode API without opening a managed session first (or from a different thread than the one that started it).

Source

Thrown at src/main/java/org/apache/ibatis/session/SqlSessionManager.java:266

  public int delete(String statement) {
    return sqlSessionProxy.delete(statement);
  }

  @Override
  public int delete(String statement, Object parameter) {
    return sqlSessionProxy.delete(statement, parameter);
  }

  @Override
  public <T> T getMapper(Class<T> type) {
    return getConfiguration().getMapper(type, this);
  }

  @Override
  public Connection getConnection() {
    final SqlSession sqlSession = localSqlSession.get();
    if (sqlSession == null) {
      throw new SqlSessionException("Error:  Cannot get connection.  No managed session is started.");
    }
    return sqlSession.getConnection();
  }

  @Override
  public void clearCache() {
    final SqlSession sqlSession = localSqlSession.get();
    if (sqlSession == null) {
      throw new SqlSessionException("Error:  Cannot clear the cache.  No managed session is started.");
    }
    sqlSession.clearCache();
  }

  @Override
  public void commit() {
    final SqlSession sqlSession = localSqlSession.get();
    if (sqlSession == null) {
      throw new SqlSessionException("Error:  Cannot commit.  No managed session is started.");

View on GitHub (pinned to 008069adb1)

Solutions

  1. Call sqlSessionManager.startManagedSession() (optionally with ExecutorType/autoCommit) before any lifecycle call on that thread.
  2. Ensure start and use happen on the same thread; for async work, start a fresh managed session inside the worker thread.
  3. Prefer the mapper proxy style (getMapper without managed session) so the manager opens/closes sessions per operation automatically.

Example fix

// before
Connection c = sqlSessionManager.getConnection(); // throws
// after
sqlSessionManager.startManagedSession();
try {
  Connection c = sqlSessionManager.getConnection();
} finally {
  sqlSessionManager.close();
}
Defensive patterns

Strategy: validation

Validate before calling

if (!sqlSessionManager.isManagedSessionStarted()) {
  sqlSessionManager.startManagedSession();
}
Connection c = sqlSessionManager.getConnection();

Try / catch

try { ... } catch (SqlSessionException e) { /* check 'No managed session is started' -> fix lifecycle */ throw e; }

Prevention

When it happens

Trigger: Calling SqlSessionManager.getConnection() before startManagedSession() on the same thread; starting the managed session in one thread (e.g. servlet filter) and calling getConnection() in another (e.g. async task) since ThreadLocal does not propagate; calling after close() removed the thread-local.

Common situations: Integrating SqlSessionManager with custom transaction code and forgetting the start call in one code path; moving work to an Executor/thread pool where the ThreadLocal session is absent; filter ordering so the DAO runs before the session-start filter.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/15f9ed95cbc513bb. Report an issue: GitHub.