{"record":{"id":"88cce4792e6fe522","repo":"mybatis/mybatis-3","slug":"got-interrupted-while-trying-to-acquire-lock-for-k","errorCode":null,"errorMessage":"Got interrupted while trying to acquire lock for key {key}","messagePattern":"Got interrupted while trying to acquire lock for key (.+?)","errorType":"exception","errorClass":"CacheException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java","lineNumber":107,"sourceCode":"  private void acquireLock(Object key) {\n    CountDownLatch newLatch = new CountDownLatch(1);\n    while (true) {\n      CountDownLatch latch = locks.putIfAbsent(key, newLatch);\n      if (latch == null) {\n        break;\n      }\n      try {\n        if (timeout > 0) {\n          boolean acquired = latch.await(timeout, TimeUnit.MILLISECONDS);\n          if (!acquired) {\n            throw new CacheException(\n                \"Couldn't get a lock in \" + timeout + \" for the key \" + key + \" at the cache \" + delegate.getId());\n          }\n        } else {\n          latch.await();\n        }\n      } catch (InterruptedException e) {\n        throw new CacheException(\"Got interrupted while trying to acquire lock for key \" + key, e);\n      }\n    }\n  }\n\n  private void releaseLock(Object key) {\n    CountDownLatch latch = locks.remove(key);\n    if (latch == null) {\n      throw new IllegalStateException(\"Detected an attempt at releasing unacquired lock. This should never happen.\");\n    }\n    latch.countDown();\n  }\n\n  public long getTimeout() {\n    return timeout;\n  }\n\n  public void setTimeout(long timeout) {\n    this.timeout = timeout;","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ntry { cache.getObject(key); } catch (CacheException e) { /* ignored */ }\n\n// after\ntry {\n  cache.getObject(key);\n} catch (CacheException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt();\n    throw new CancellationException(\"query interrupted\", e);\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":null,"tryCatchPattern":"catch (CacheException e) { if (e.getCause() instanceof InterruptedException) { Thread.currentThread().interrupt(); cancelTask(); return; } throw e; }","preventionTips":["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"],"tags":["mybatis","cache","concurrency","interruption"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}