{"record":{"id":"c793a0773f013726","repo":"brettwooldridge/HikariCP","slug":"the-pool-is-currently-suspended-and-configured-to","errorCode":null,"errorMessage":"The pool is currently suspended and configured to throw exceptions upon acquisition","messagePattern":"The pool is currently suspended and configured to throw exceptions upon acquisition","errorType":"exception","errorClass":"SQLTransientException","httpStatus":null,"severity":"warning","filePath":"src/main/java/com/zaxxer/hikari/util/SuspendResumeLock.java","lineNumber":69,"sourceCode":"    * Default constructor\n    */\n   public SuspendResumeLock()\n   {\n      this(true);\n   }\n\n   private SuspendResumeLock(final boolean createSemaphore)\n   {\n      acquisitionSemaphore = (createSemaphore ? new Semaphore(MAX_PERMITS, true) : null);\n   }\n\n   public void acquire() throws SQLException\n   {\n      if (acquisitionSemaphore.tryAcquire()) {\n         return;\n      }\n      else if (Boolean.getBoolean(\"com.zaxxer.hikari.throwIfSuspended\")) {\n         throw new SQLTransientException(\"The pool is currently suspended and configured to throw exceptions upon acquisition\");\n      }\n\n      acquisitionSemaphore.acquireUninterruptibly();\n   }\n\n   public void release()\n   {\n      acquisitionSemaphore.release();\n   }\n\n   public void suspend()\n   {\n      acquisitionSemaphore.acquireUninterruptibly(MAX_PERMITS);\n   }\n\n   public void resume()\n   {\n      acquisitionSemaphore.release(MAX_PERMITS);","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/brettwooldridge/HikariCP/blob/a4d93f4f85517f90e632b795486d7102e933d7ff/src/main/java/com/zaxxer/hikari/util/SuspendResumeLock.java#L51-L87","documentation":"SuspendResumeLock.acquire() normally blocks when the pool is suspended (all permits drained). If the system property com.zaxxer.hikari.throwIfSuspended=true, acquiring while suspended instead throws SQLTransientException immediately, letting callers fail fast instead of hanging during suspension.","triggerScenarios":"Pool suspended via suspendPool() (allowPoolSuspension=true) during DB maintenance/failover, and getConnection() called while suspended with -Dcom.zaxxer.hikari.throwIfSuspended=true set; ops tooling that suspends while traffic still arrives.","commonSituations":"Planned maintenance windows, blue/green failover automation that suspends pools, health-check probes hitting a suspended pool.","solutions":["If fast failure is desired: catch SQLTransientException and retry after a backoff until resumePool() completes","Schedule work to stop before suspendPool() (quiesce) and resume after maintenance","If blocking is acceptable, remove -Dcom.zaxxer.hikari.throwIfSuspended so acquisition waits for resume","Bound retries with a deadline shorter than the expected maintenance window and degrade gracefully"],"exampleFix":"// before\nConnection c = ds.getConnection(); // throws SQLTransientException while suspended\n\n// after\nSQLException last = null;\nfor (int i = 0; i < 30; i++) {\n   try { return ds.getConnection(); }\n   catch (SQLTransientException e) { last = e; Thread.sleep(1000); }\n}\nthrow last;","handlingStrategy":"retry","validationCode":"// before borrowing, check pool state via MXBean if suspension is possible\nif (hikariPoolMXBean != null && suspended) { /* wait or degrade */ }","typeGuard":null,"tryCatchPattern":"try { conn = ds.getConnection(); }\ncatch (SQLTransientException e) {\n    if (e.getMessage().contains(\"currently suspended\")) { backoffAndRetry(); }\n    else throw e;\n}","preventionTips":["Quiesce traffic before suspendPool","Pair suspend/resume in try/finally in ops scripts","Decide deliberately whether throwIfSuspended is set, and code callers accordingly"],"tags":["hikaricp","suspension","transient","maintenance"],"backgroundTag":null,"analyzedSha":"a4d93f4f85517f90e632b795486d7102e933d7ff","analyzedAt":"2026-08-14T12:11:37.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}