mybatis/mybatis-3 · error · CacheException

Got interrupted while trying to acquire lock for key

Error message

Got interrupted while trying to acquire lock for key {key}

What it means

Thrown by BlockingCache.acquireLock() when the thread waiting on a key's CountDownLatch is interrupted while blocked. Unlike the timeout case this is a thread-lifecycle event (shutdown, thread pool interrupt, test harness interruption), and the original InterruptedException is chained as the cause so the interrupt status and context are preserved.

Solutions

  1. Restore the interrupt status in your catch block (Thread.currentThread().interrupt()) and treat the query as cancelled — do not retry blindly
  2. Avoid interrupting threads that may be inside mybatis cache waits; use cooperative cancellation (Future.cancel(false), flags)
  3. Tune blockingTimeout so waits are bounded and shutdown drains quickly

Example fix

// before
try { cache.getObject(key); } catch (CacheException e) { /* ignored */ }

// after
try {
  cache.getObject(key);
} catch (CacheException e) {
  if (e.getCause() instanceof InterruptedException) {
    Thread.currentThread().interrupt();
    throw new CancellationException("query interrupted", e);
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Try / catch

catch (CacheException e) { if (e.getCause() instanceof InterruptedException) { Thread.currentThread().interrupt(); cancelTask(); return; } throw e; }

Prevention

When it happens

Trigger: A thread waiting inside BlockingCache.getObject() for another thread's query to finish receives Thread.interrupt() — e.g. application shutdown draining executor threads, a servlet request timeout thread group interrupt, orJUnit/TimeboundUnit timeout teardown while a cache-blocking query is in flight.

Common situations: Graceful shutdown interrupts worker threads mid-query; async frameworks (WebFlux/CompletableFuture ondedicated pools) cancelling tasks; test harness timeouts interrupting blocked queries; misbehaving middleware interrupting threads it does not own.

Related errors


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

Appendix: source

Thrown at src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java:107

  private void acquireLock(Object key) {
    CountDownLatch newLatch = new CountDownLatch(1);
    while (true) {
      CountDownLatch latch = locks.putIfAbsent(key, newLatch);
      if (latch == null) {
        break;
      }
      try {
        if (timeout > 0) {
          boolean acquired = latch.await(timeout, TimeUnit.MILLISECONDS);
          if (!acquired) {
            throw new CacheException(
                "Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId());
          }
        } else {
          latch.await();
        }
      } catch (InterruptedException e) {
        throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e);
      }
    }
  }

  private void releaseLock(Object key) {
    CountDownLatch latch = locks.remove(key);
    if (latch == null) {
      throw new IllegalStateException("Detected an attempt at releasing unacquired lock. This should never happen.");
    }
    latch.countDown();
  }

  public long getTimeout() {
    return timeout;
  }

  public void setTimeout(long timeout) {
    this.timeout = timeout;

View on GitHub (pinned to 008069adb1)