{"record":{"id":"73194911e0afd2f6","repo":"apache/druid","slug":"can-t-stop-731949","errorCode":null,"errorMessage":"can't stop.","messagePattern":"can't stop\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-core/kubernetes-extensions/src/main/java/org/apache/druid/k8s/discovery/LeaderElectorAsyncWrapper.java","lineNumber":100,"sourceCode":"              }\n              catch (Throwable ex) {\n                LOGGER.error(ex, \"Exception in K8s LeaderElector.run()\");\n              }\n            }\n          }\n      ));\n      lifecycleLock.started();\n    }\n    finally {\n      lifecycleLock.exitStart();\n    }\n  }\n\n  @Override\n  public void close()\n  {\n    if (!lifecycleLock.canStop()) {\n      throw new ISE(\"can't stop.\");\n    }\n\n    try {\n      futureRef.get().cancel(true);\n      executor.shutdownNow();\n      if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {\n        LOGGER.warn(\"Failed to terminate [%s] executor.\", this.getClass().getSimpleName());\n      }\n    }\n    catch (InterruptedException ex) {\n      Thread.currentThread().interrupt();\n    }\n  }\n\n  public String getCurrentLeader()\n  {\n    return k8sLeaderElector.getCurrentLeader();\n  }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kubernetes-extensions/src/main/java/org/apache/druid/k8s/discovery/LeaderElectorAsyncWrapper.java#L82-L118","documentation":"LeaderElectorAsyncWrapper.close() throws this IllegalStateException when LifecycleLock.canStop() returns false - the elector was never started via run(), is already closed, or is mid-close. The close path cancels the election future and shuts down the executor, which only exist after a successful run().","triggerScenarios":"Calling close() before run(); calling close() twice (double close / try-with-resources plus manual close); close() racing run(); run() previously failed leaving state stuck.","commonSituations":"Overlord shutdown where the elector failed to start; cleanup code closing all services unconditionally; wrapping an unstarted elector in try-with-resources.","solutions":["Only close() after run() has been called successfully","Guard close with try-catch of IllegalStateException if the start state is unknown","Avoid double-close: don't both register with Lifecycle and close manually","If close must be idempotent, check an internal 'started' flag before delegating"],"exampleFix":"// before\nelector.close(); // ISE if run() never called\n// after\nif (started) {\n  elector.close();\n  started = false;\n}","handlingStrategy":"try-catch","validationCode":"if (!electorRunning) { return; }","typeGuard":null,"tryCatchPattern":"try { elector.close(); } catch (IllegalStateException e) { /* never started or already closed */ }","preventionTips":["Close only after run() succeeded","Track started state before closing","Avoid registering the elector in Lifecycle AND closing it manually"],"tags":["lifecycle","illegal-state","leader-election","kubernetes"],"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"}