apache/pulsar · error · IllegalStateException
No latest service lookup data found.
Error message
No latest service lookup data found.
What it means
After collecting available brokers, redirectIfLoadBalancerOnBrokerIsNotExpected picks the broker with the latest start timestamp as the 'latest service'. If no entry won (map non-empty but no data set, defensive case), the future fails with IllegalStateException 'No latest service lookup data found.'
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/manager/RedirectManagerForLoadManagerMigration.java:117
boolean debug = ExtensibleLoadManagerImpl.debug(pulsar.getConfiguration(), log);
return getAvailableBrokerLookupDataAsync().thenApply(lookupDataMap -> {
if (lookupDataMap.isEmpty()) {
String errorMsg = "No available broker found.";
log.warn(errorMsg);
throw new IllegalStateException(errorMsg);
}
AtomicReference<BrokerLookupData> latestServiceLookupData = new AtomicReference<>();
AtomicLong lastStartTimestamp = new AtomicLong(0L);
lookupDataMap.forEach((key, value) -> {
if (lastStartTimestamp.get() <= value.getStartTimestamp()) {
lastStartTimestamp.set(value.getStartTimestamp());
latestServiceLookupData.set(value);
}
});
if (latestServiceLookupData.get() == null) {
String errorMsg = "No latest service lookup data found.";
log.warn(errorMsg);
throw new IllegalStateException(errorMsg);
}
if (Objects.equals(latestServiceLookupData.get().getLoadManagerClassName(), currentLMClassName)) {
if (debug) {
log.info().attr("name", currentLMClassName)
.log("No need to redirect, current load manager class name");
}
return Optional.empty();
}
var serviceLookupDataObj = latestServiceLookupData.get();
var candidateBrokers = new ArrayList<BrokerLookupData>();
lookupDataMap.forEach((key, value) -> {
if (Objects.equals(value.getLoadManagerClassName(), serviceLookupDataObj.getLoadManagerClassName())) {
candidateBrokers.add(value);
}
});
var selectedBroker = candidateBrokers.get((int) (Math.random() * candidateBrokers.size()));
View on GitHub (pinned to 820761864e)
Solutions
- Verify broker lookup data has sane non-negative start timestamps; re-register/restart brokers with bad data.
- Re-check metadata-store connectivity — a concurrent deregistration of all brokers can empty the map mid-flight.
- Retry the lookup; this is usually transient.
- In tests, ensure stubbed BrokerLookupData has startTimestamp >= 0.
Example fix
// before (test) new BrokerLookupData(...).setStartTimestamp(-1); // after new BrokerLookupData(...).setStartTimestamp(System.currentTimeMillis());
Defensive patterns
Strategy: retry
Validate before calling
if (lookupDataMap.isEmpty()) throw new RestException(Response.Status.SERVICE_UNAVAILABLE, "no brokers");
boolean anyValid = lookupDataMap.values().stream()
.anyMatch(d -> d.getStartTimestamp() >= 0);
if (!anyValid) throw new RestException(Response.Status.SERVICE_UNAVAILABLE, "invalid lookup data"); Try / catch
CompletableFuture.supplyAsync(() -> redirectIfLoadBalancerOnBrokerIsNotExpected(...))
.orTimeout(3, TimeUnit.SECONDS)
.exceptionally(ex -> { /* retry lookup once, then 503 */ return null; }); Prevention
- Ensure broker lookup data always has non-negative start timestamps.
- Treat empty/volatile broker registries as transient and retry with bounded backoff.
- Watch for metadata-store watch storms that empty snapshots mid-read.
When it happens
Trigger: getAvailableBrokerLookupDataAsync returned a non-empty map but the forEach never set latestServiceLookupData — only possible with pathological lookup data (e.g. negative/NaN-like start timestamps never satisfying lastStartTimestamp <= value.getStartTimestamp() for a first negative value... in practice the initial 0L is overwritten by any timestamp >= 0, so this fires only when the map was emptied concurrently or timestamps are negative).
Common situations: Race where the broker registry is emptied between the emptiness check and the iteration, or corrupted start timestamps in broker lookup data; mostly seen in tests stubbing lookup data with negative start timestamps.
Related errors
- No available broker found.
- ${loadManagerClass} does not support this operation
- Message not found
- Unable to determine latest version since broker version map
- No version string in lookup data for broker "${brokerId}"
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/e16aeecf418c0968.
Report an issue: GitHub.