apache/pulsar · warning · RestException
Topic does not exist
Error message
Topic does not exist
What it means
internalGetStats validates access then looks up the in-memory ProxyTopicStat for the given topic name. If no stats object exists the topic has no active proxy handlers, so it returns HTTP 404 with 'Topic does not exist' via RestException. This is a lookup miss on the proxy's live handler registry, not a broker-side topic check.
Source
Thrown at pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/WebSocketProxyStatsBase.java:51
@CustomLog
public class WebSocketProxyStatsBase extends WebSocketWebResource {
protected Collection<Metrics> internalGetMetrics() throws Exception {
// Ensure super user access only
validateSuperUserAccess();
try {
return service().getProxyStats().getMetrics();
} catch (Exception e) {
log.error().attr("clientAppId", clientAppId()).exception(e).log("Failed to generate metrics");
throw new RestException(e);
}
}
protected ProxyTopicStat internalGetStats(TopicName topicName) {
validateUserAccess(topicName);
ProxyTopicStat stats = getStat(topicName);
if (stats == null) {
throw new RestException(Status.NOT_FOUND, "Topic does not exist");
}
return stats;
}
protected Map<String, ProxyTopicStat> internalGetProxyStats() {
validateSuperUserAccess();
return getStat();
}
private ProxyTopicStat getStat(TopicName topicName) {
String topicNameStr = topicName.toString();
if (!service().getProducers().containsKey(topicNameStr) && !service().getConsumers().containsKey(topicNameStr)
&& !service().getReaders().containsKey(topicNameStr)) {
log.warn().attr("exist", topicNameStr).log("topic doesn't exist");
throw new RestException(Status.NOT_FOUND, "Topic does not exist");
}
ProxyTopicStat topicStat = new ProxyTopicStat();
if (service().getProducers().containsKey(topicNameStr)) {View on GitHub (pinned to 820761864e)
Solutions
- Open a WebSocket producer/consumer/reader on the topic before requesting its proxy stats
- Verify the exact topic name (tenant/namespace/topic) and that you are querying the proxy instance that holds the connection
- Handle HTTP 404 from the stats endpoint gracefully — treat it as 'no active proxy sessions' rather than a hard failure
- Aggregate stats across proxy instances via broker-level topic stats if the connection may live on another node
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side: only request stats when a connection is known active
if (!activeConnections.containsKey(topicName)) { throw new IllegalStateException("no active proxy session for " + topicName); } Try / catch
Response r = target.path(topicName + "/stats").get(); if (r.getStatus() == 404) { return Optional.empty(); } return Optional.of(r.readEntity(ProxyTopicStat.class)); Prevention
- Poll stats only while the WebSocket session is open
- Treat 404 on proxy stats as 'no live sessions', not an error
- Target the proxy instance that owns the connection (sticky routing)
- Double-check topic name spelling/tenant/namespace
When it happens
Trigger: GET /admin/v2/websocket/.../stats/<topic> where the topic has no currently open WebSocket producers, consumers, or readers in this proxy instance (getStat(topicName) returned null).
Common situations: Querying stats after the client disconnected; querying the wrong topic name/tenant/namespace; hitting a different proxy instance than the one holding the connection (no shared stats store); typo in the topic path.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- domain() invoked from wrong resource
- Topic does not exist: ${persistentBase}
- Scalable topic not found: ${tn}
- Segment topic not found: ${segmentTopic}
- Segment topic not loaded: ${segmentTopic}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/d94eaae9abd49f77.
Report an issue: GitHub.