{"record":{"id":"36478627b08e339b","repo":"apache/pulsar","slug":"leader-cannot-be-determined","errorCode":null,"errorMessage":"Leader cannot be determined","messagePattern":"Leader cannot be determined","errorType":"http","errorClass":"RestException","httpStatus":500,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java","lineNumber":108,"sourceCode":"        throwIfNotSuperUser(authParams, \"get cluster\");\n\n        List<WorkerInfo> workers = worker().getMembershipManager().getCurrentMembership();\n        return workers;\n    }\n\n    @Override\n    public WorkerInfo getClusterLeader(AuthenticationParameters authParams) {\n        if (!isWorkerServiceAvailable()) {\n            throwUnavailableException();\n        }\n\n        throwIfNotSuperUser(authParams, \"get cluster leader\");\n\n        MembershipManager membershipManager = worker().getMembershipManager();\n        WorkerInfo leader = membershipManager.getLeader();\n\n        if (leader == null) {\n            throw new RestException(Status.INTERNAL_SERVER_ERROR, \"Leader cannot be determined\");\n        }\n\n        return leader;\n    }\n\n    @Override\n    public Map<String, Collection<String>> getAssignments(AuthenticationParameters authParams) {\n        if (!isWorkerServiceAvailable()) {\n            throwUnavailableException();\n        }\n\n        throwIfNotSuperUser(authParams, \"get cluster assignments\");\n\n        FunctionRuntimeManager functionRuntimeManager = worker().getFunctionRuntimeManager();\n        Map<String, Map<String, Assignment>> assignments = functionRuntimeManager.getCurrentAssignments();\n        Map<String, Collection<String>> ret = new HashMap<>();\n        for (Map.Entry<String, Map<String, Assignment>> entry : assignments.entrySet()) {\n            ret.put(entry.getKey(), entry.getValue().keySet());","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java#L90-L126","documentation":"getClusterLeader returns 500 with this message when the worker's MembershipManager reports no current leader (getLeader() returns null). The functions worker cluster has not elected (or has lost) a coordinator.","triggerScenarios":"GET /worker/leader (getClusterLeader) during worker startup, a leadership election, or when all workers have lost coordination (e.g. metadata store partition).","commonSituations":"Fresh cluster where election has not completed; metadata store (ZooKeeper et al.) outage causing leader loss; all workers restarting simultaneously; split-brain healing period after network issues.","solutions":["Wait for leader election to complete and retry the request","Check metadata store connectivity for all workers","Inspect worker logs for election/coordination errors","Verify at least one functions worker is fully started and registered in the membership manager"],"exampleFix":"// before\nWorkerInfo leader = admin.worker().getClusterLeader(); // during startup -> 500\n// after\nawait().atMost(30, SECONDS).until(() -> {\n    try { admin.worker().getClusterLeader(); return true; }\n    catch (PulsarAdminException e) { return false; }\n});","handlingStrategy":"retry","validationCode":"// no client-side pre-check exists; verify cluster health first\ntry { admin.worker().getCluster(); } // will also fail without a healthy worker cluster\ncatch (PulsarAdminException e) { throw new IllegalStateException(\"worker cluster unhealthy\", e); }","typeGuard":"boolean leaderAvailable(PulsarAdmin admin) {\n    try { admin.worker().getClusterLeader(); return true; }\n    catch (PulsarAdminException e) { return false; }\n}","tryCatchPattern":"Retryer<WorkerInfo> r = RetryerBuilder.<WorkerInfo>newBuilder()\n    .retryIfException(e -> e instanceof PulsarAdminException\n        && ((PulsarAdminException) e).getStatusCode() == 500)\n    .withWaitStrategy(WaitStrategies.exponentialWait())\n    .withStopStrategy(StopStrategies.stopAfterDelay(Duration.ofSeconds(30).toMillis()))\n    .build();\nWorkerInfo leader = r.call(() -> admin.worker().getClusterLeader());","preventionTips":["Wait for cluster startup to complete before querying the leader","Monitor metadata store connectivity for all workers","Alert on leader absence rather than treating it as fatal immediately","Ensure at least one worker stays running during rolling restarts"],"tags":["pulsar-functions","worker-cluster","leader-election"],"backgroundTag":"leader-not-available","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}