{"record":{"id":"0d3562d27f6cec33","repo":"apache/druid","slug":"can-t-start-0d3562","errorCode":null,"errorMessage":"can't start","messagePattern":"can't start","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulLeaderSelector.java","lineNumber":141,"sourceCode":"  @Override\n  public boolean isLeader()\n  {\n    return leader.get();\n  }\n\n  @Override\n  public int localTerm()\n  {\n    return term.get();\n  }\n\n  @Override\n  public void registerListener(Listener listener)\n  {\n    Preconditions.checkArgument(listener != null, \"listener is null\");\n\n    if (!lifecycleLock.canStart()) {\n      throw new ISE(\"can't start\");\n    }\n\n    try {\n      this.listener = listener;\n      this.executorService = Execs.scheduledSingleThreaded(\"ConsulLeaderSelector-%d\");\n      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  }","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulLeaderSelector.java#L123-L159","documentation":"ConsulLeaderSelector.registerListener() throws this ISE when the lifecycle lock refuses the start, meaning the selector was already started (listener already registered) or is being stopped. registerListener is itself the 'start' of the leader-election machinery (session keeper and scheduled executors).","triggerScenarios":"Calling registerListener() more than once on the same ConsulLeaderSelector, or calling it after unregisterListener() / during shutdown so canStart() returns false.","commonSituations":"Re-registering a leadership listener on hot reconfiguration, registering the same selector from two services, or registering after a stop during server teardown.","solutions":["Register the listener exactly once, at service startup.","Use a new ConsulLeaderSelector instance if you need to re-register after unregistering.","Guard registration with a boolean/AtomicBoolean in the calling service.","Ensure unregisterListener() is not concurrently executing when registerListener() is called."],"exampleFix":"// before\nleaderSelector.registerListener(listener);\n...\nleaderSelector.registerListener(listener); // ISE: can't start\n// after\nif (registered.compareAndSet(false, true)) {\n  leaderSelector.registerListener(listener);\n}","handlingStrategy":"validation","validationCode":"if (!registered.compareAndSet(false, true)) { return; }\nleaderSelector.registerListener(listener);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register the listener once at service startup, never on reconfiguration.","Unregister by discarding the selector and creating a fresh one if re-registration is needed.","Ensure register/unregister are not called concurrently."],"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"}