{"record":{"id":"a797c7b018003de9","repo":"apache/druid","slug":"can-t-stop-a797c7","errorCode":null,"errorMessage":"can't stop","messagePattern":"can't stop","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulLeaderSelector.java","lineNumber":165,"sourceCode":"      this.sessionKeeperService = Execs.scheduledSingleThreaded(\"ConsulSessionKeeper-%d\");\n\n      startLeaderElection();\n\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    LOGGER.info(\"Unregistering leader selector for [%s]\", lockKey);\n    stopping = true;\n\n    try {\n      if (leader.get()) {\n        try {\n          listener.stopBeingLeader();\n        }\n        catch (Exception e) {\n          LOGGER.error(e, \"Exception while stopping being leader\");\n        }\n        leader.set(false);\n      }\n\n      // Destroying session releases the Consul lock, allowing another node to become leader\n      if (sessionId != null) {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulLeaderSelector.java#L147-L183","documentation":"ConsulLeaderSelector.unregisterListener() throws this ISE when the lifecycle lock says it cannot stop, i.e. the selector was never started via registerListener() or unregister is called twice/concurrently with registration.","triggerScenarios":"Calling unregisterListener() without a prior successful registerListener(), calling it twice, or racing it against registerListener().","commonSituations":"Teardown code that always unregisters regardless of registration state, a registerListener() that failed earlier (e.g. Consul connection error) leaving the selector unstarted, or duplicate shutdown hooks.","solutions":["Only call unregisterListener() after registerListener() completed successfully.","Track registration state (AtomicBoolean) in the owning service before unregistering.","Create the selector and register the listener in the same startup path so states stay paired.","If registerListener() failed, let its error handling clean up rather than calling unregisterListener()."],"exampleFix":"// before\nservice.stop() { leaderSelector.unregisterListener(); } // ISE if never registered\n// after\nif (registered) {\n  leaderSelector.unregisterListener();\n  registered = false;\n}","handlingStrategy":"validation","validationCode":"if (registered.compareAndSet(true, false)) { leaderSelector.unregisterListener(); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only unregister after a successful registerListener().","Track registration state in the owning service.","Let failed registrations clean up their own resources."],"tags":["lifecycle","consul","leader-election"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}