{"record":{"id":"ac0830f0092f82c4","repo":"apache/druid","slug":"runtimeexception-ac0830","errorCode":null,"errorMessage":"RuntimeException","messagePattern":"RuntimeException","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions-core/kubernetes-extensions/src/main/java/org/apache/druid/k8s/discovery/K8sDruidLeaderSelector.java","lineNumber":112,"sourceCode":"            leader = false;\n            listener.stopBeingLeader();\n          }\n          catch (Throwable ex) {\n            LOGGER.makeAlert(ex, \"listener.stopBeingLeader() failed. Unable to stopBeingLeader\").emit();\n          }\n        }\n    );\n  }\n\n  @Nullable\n  @Override\n  public String getCurrentLeader()\n  {\n    try {\n      return leaderLatch.getCurrentLeader();\n    }\n    catch (Exception e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  @Override\n  public boolean isLeader()\n  {\n    return leader;\n  }\n\n  @Override\n  public int localTerm()\n  {\n    return term;\n  }\n\n  @Override\n  public void registerListener(DruidLeaderSelector.Listener listener)\n  {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kubernetes-extensions/src/main/java/org/apache/druid/k8s/discovery/K8sDruidLeaderSelector.java#L94-L130","documentation":"K8sDruidLeaderSelector.getCurrentLeader() catches any Exception from the delegate leader latch's getCurrentLeader and rethrows it as a bare RuntimeException, losing the original type and message context. The underlying cause is a Kubernetes API failure or elector state error while resolving the current leader.","triggerScenarios":"Calling getCurrentLeader on K8sDruidLeaderSelector when the underlying K8sLeaderElector/leaderLatch fails — e.g. ApiException from fetching the lock, or the latch isn't started yet.","commonSituations":"Querying the leader before registerListener/startLeaderElector; K8s API errors (RBAC/auth/network) when reading the Lease; concurrent lifecycle calls.","solutions":["Inspect the RuntimeException's cause (getCause()) for the real ApiException.","Ensure registerListener() was called and the leader elector started before querying the leader.","Fix the underlying K8s access issue (RBAC, token, namespace) per the cause.","Prefer logging-and-defaulting over rethrow if the caller only needs a best-effort leader hint."],"exampleFix":"// before\ncatch (Exception e) { throw new RuntimeException(e); }\n// after\ncatch (Exception e) { throw new RE(e, \"Failed to get current leader for [%s]\", latchName); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"boolean leaderElectorStarted(K8sDruidLeaderSelector s) { try { s.getCurrentLeader(); return true; } catch (RuntimeException e) { return false; } }","tryCatchPattern":"try {\n  String leader = leaderSelector.getCurrentLeader();\n} catch (RuntimeException e) {\n  Throwable cause = e.getCause();\n  LOG.warn(cause, \"Leader lookup failed; treating as unknown\");\n  leader = null;\n}","preventionTips":["Call registerListener and wait for the elector to start before querying the leader.","Always inspect getCause() — the bare RuntimeException hides the real ApiException.","Handle 'no leader yet' as a normal state during startup.","Fix RBAC/namespace issues surfaced by the cause."],"tags":["leader-election","kubernetes","runtime-exception","lifecycle"],"backgroundTag":"http-error-response","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"}