{"record":{"id":"ab546ce9cc4c79b4","repo":"apache/druid","slug":"failed-to-close-leaderlatch","errorCode":null,"errorMessage":"Failed to close LeaderLatch.","messagePattern":"Failed to close LeaderLatch\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/main/java/org/apache/druid/curator/discovery/CuratorDruidLeaderSelector.java","lineNumber":208,"sourceCode":"\n      lifecycleLock.started();\n    }\n    catch (Exception ex) {\n      throw new RuntimeException(ex);\n    }\n    finally {\n      lifecycleLock.exitStart();\n    }\n  }\n\n  @Override\n  public void unregisterListener()\n  {\n    if (!lifecycleLock.canStop()) {\n      throw new ISE(\"can't stop.\");\n    }\n\n    CloseableUtils.closeAndSuppressExceptions(leaderLatch.get(), e -> log.warn(e, \"Failed to close LeaderLatch.\"));\n    listenerExecutor.shutdownNow();\n  }\n\n  private void stopAndCreateNewLeaderLatch()\n  {\n    CloseableUtils.closeAndSuppressExceptions(\n        createNewLeaderLatchWithListener(),\n        e -> log.warn(\"Could not close old leader latch; continuing with new one anyway.\")\n    );\n  }\n\n  private void startLeaderLatch()\n  {\n    try {\n      //Small delay before starting the latch so that others waiting are chosen to become leader.\n      Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));\n      leaderLatch.get().start();\n    }","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/curator/discovery/CuratorDruidLeaderSelector.java#L190-L226","documentation":"In unregisterListener(), CloseableUtils.closeAndSuppressExceptions failed to close the current LeaderLatch (e.g. it was already closed or the Curator client's connection was broken) and the exception is logged as a warning rather than propagated. Listener registration is torn down regardless.","triggerScenarios":"Calling unregisterListener() when the leader latch was already closed (stopAndCreateNewLeaderLatch or a previous unregister), or when the underlying CuratorFramework/ZooKeeper session is broken so the close RPC fails.","commonSituations":"Service shutdown during a ZK outage, double lifecycle stop, or unregister racing with an in-flight latch swap after leadership loss.","solutions":["Verify lifecycle ordering: call unregisterListener() exactly once per CuratorDruidLeaderSelector, from the stop phase only.","Check whether ZK connectivity was down at shutdown; if so the warning is expected and the ephemeral node will be cleaned by session expiry.","Look for a preceding 'Could not close old leader latch' warning indicating the latch was swapped concurrently.","If the latch instance is stale, restart the service to rebuild a fresh latch."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// tolerate latch cleanup failure during shutdown\ntry {\n  leaderSelector.unregisterListener();\n} catch (Exception e) {\n  log.warn(e, \"Leader latch cleanup failed during shutdown; ephemeral node expires with session\");\n}","preventionTips":["Call unregisterListener() exactly once, in the lifecycle stop phase.","Check ZK health before/after shutdown if this warning appears.","Rely on ZK session expiry to clean ephemeral leader nodes when close fails."],"tags":["zookeeper","curator","leader-election","shutdown"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}