{"record":{"id":"4e7a8c80db4c002b","repo":"apache/pulsar","slug":"no-available-broker-found","errorCode":null,"errorMessage":"No available broker found.","messagePattern":"No available broker found\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/manager/RedirectManagerForLoadManagerMigration.java","lineNumber":104,"sourceCode":"     * Redirect the request to another broker if the load balancer on the current broker is using the load manager\n     * of the latest service lookup data available in the metadata store.\n     *\n     * @param options lookup options\n     * @return lookup result\n     */\n    public CompletableFuture<Optional<LookupResult>> redirectIfLoadBalancerOnBrokerIsNotExpected(\n            LookupOptions options) {\n        if (!pulsar.getConfiguration().isLoadManagerMigrationEnabled()) {\n            // no-op when load manager migration is disabled.\n            return CompletableFuture.completedFuture(Optional.empty());\n        }\n        String currentLMClassName = pulsar.getConfiguration().getLoadManagerClassName();\n        boolean debug = ExtensibleLoadManagerImpl.debug(pulsar.getConfiguration(), log);\n        return getAvailableBrokerLookupDataAsync().thenApply(lookupDataMap -> {\n            if (lookupDataMap.isEmpty()) {\n                String errorMsg = \"No available broker found.\";\n                log.warn(errorMsg);\n                throw new IllegalStateException(errorMsg);\n            }\n            AtomicReference<BrokerLookupData> latestServiceLookupData = new AtomicReference<>();\n            AtomicLong lastStartTimestamp = new AtomicLong(0L);\n            lookupDataMap.forEach((key, value) -> {\n                if (lastStartTimestamp.get() <= value.getStartTimestamp()) {\n                    lastStartTimestamp.set(value.getStartTimestamp());\n                    latestServiceLookupData.set(value);\n                }\n            });\n            if (latestServiceLookupData.get() == null) {\n                String errorMsg = \"No latest service lookup data found.\";\n                log.warn(errorMsg);\n                throw new IllegalStateException(errorMsg);\n            }\n\n            if (Objects.equals(latestServiceLookupData.get().getLoadManagerClassName(), currentLMClassName)) {\n                if (debug) {\n                    log.info().attr(\"name\", currentLMClassName)","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/manager/RedirectManagerForLoadManagerMigration.java#L86-L122","documentation":"During load-manager migration, RedirectManagerForLoadManagerMigration.redirectIfLoadBalancerOnBrokerIsNotExpected fetches the available-broker lookup data; if the map is empty there is no broker to redirect to or to evaluate, so the returned future fails with IllegalStateException 'No available broker found.'","triggerScenarios":"A lookup reaches redirectIfLoadBalancerOnBrokerIsNotExpected while getAvailableBrokerLookupDataAsync returns an empty map (no brokers registered in the extensible load manager's broker registry).","commonSituations":"Cluster just started and no broker has published load data yet, metadata store connectivity issues wiped/emptied the registry, or all brokers were excluded/deregistered (shutdown, crash).","solutions":["Wait for brokers to start and publish load data, then retry the lookup.","Check broker logs and the metadata store (e.g. /loadbalance/brokers in ZooKeeper et al.) for registered brokers; fix connectivity if empty.","Ensure at least one broker is running and registered with the ExtensibleLoadManager before sending lookups.","Catch the IllegalStateException in the lookup path and return a 503 'Service unavailable' style response to clients."],"exampleFix":"// before\nreturn redirectIfLoadBalancerOnBrokerIsNotExpected(...);\n// after\nreturn redirectIfLoadBalancerOnBrokerIsNotExpected(...)\n    .exceptionally(ex -> {\n        if (ex.getCause() instanceof IllegalStateException) {\n            throw new RestException(Response.Status.SERVICE_UNAVAILABLE, \"No available brokers\");\n        }\n        throw FutureUtil.wrapToCompletionException(ex);\n    });","handlingStrategy":"try-catch","validationCode":"boolean hasBrokers = brokerRegistry.snapshot().values().stream()\n    .anyMatch(d -> !d.isBrokerShuttingDown());\nif (!hasBrokers) { /* defer/redirect with 503 */ }","typeGuard":null,"tryCatchPattern":"redirectIfLoadBalancerOnBrokerIsNotExpected(...)\n  .exceptionally(ex -> {\n      Throwable c = FutureUtil.unwrapCompletionException(ex);\n      if (c instanceof IllegalStateException && c.getMessage().contains(\"No available broker\")) {\n          throw new RestException(Response.Status.SERVICE_UNAVAILABLE, c.getMessage());\n      }\n      throw FutureUtil.wrapToCompletionException(c);\n  });","preventionTips":["Gate client traffic behind health checks that confirm at least one registered broker.","Alert when the load-manager broker registry count drops to zero.","Retry lookups with backoff during cluster startup."],"tags":["load-manager","redirect","no-brokers-available","cluster-startup"],"backgroundTag":"no-broker-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"}