mybatis/mybatis-3 · error · CacheException
Got interrupted while trying to acquire lock for key {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.
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)
Solutions
- Restore the interrupt status in your catch block (Thread.currentThread().interrupt()) and treat the query as cancelled — do not retry blindly
- Avoid interrupting threads that may be inside mybatis cache waits; use cooperative cancellation (Future.cancel(false), flags)
- 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
- Never interrupt pooled worker threads mid-query; use cooperative cancellation
- Always restore the interrupt flag when handling this error
- Bound waits with blockingTimeout so shutdown drains fast
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
- Couldn't get a lock in {timeout} for the key {key} at the ca
- cache-ref element requires a namespace attribute.
- No cache for namespace '{namespace}' could be found.
- Cache-ref not yet resolved
- Should be specified either value() or name() attribute in th
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/88cce4792e6fe522.
Report an issue: GitHub.