apache/pulsar · error · org.apache.pulsar.broker.admin.RestException
Need to provide a persistent topic name
Error message
Need to provide a persistent topic name
What it means
Thrown by validatePersistentTopicName when the addressed topic parses correctly but its domain is non-persistent (or otherwise not TopicDomain.persistent). The REST resource was created for persistent topics only, so a non-persistent:// name is rejected with HTTP 406 Not Acceptable.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java:277
*/
protected void validateCreateTopic(TopicName topicName) {
if (topicName.getDomain() == TopicDomain.persistent
&& SystemTopicNames.isTransactionInternalName(topicName)) {
log.warn().attr("topic", topicName).log("Forbidden to create transaction internal topic");
throw new RestException(Status.BAD_REQUEST, "Cannot create topic in system topic format!");
}
try {
TopicName.validateTopicNameForCreation(topicName);
} catch (IllegalArgumentException e) {
log.warn().attr("topic", topicName).log("Forbidden to create topic with an invalid name");
throw new RestException(Status.PRECONDITION_FAILED, e.getMessage());
}
}
protected void validatePersistentTopicName(String tenant, String namespace, String encodedTopic) {
validateTopicName(tenant, namespace, encodedTopic);
if (topicName.getDomain() != TopicDomain.persistent) {
throw new RestException(Status.NOT_ACCEPTABLE, "Need to provide a persistent topic name");
}
}
protected void validatePartitionedTopicName(String tenant, String namespace, String encodedTopic) {
// first, it has to be a validate topic name
validateTopicName(tenant, namespace, encodedTopic);
// second, "-partition-" is not allowed
if (encodedTopic.contains(TopicName.PARTITIONED_TOPIC_SUFFIX)) {
throw new RestException(Status.PRECONDITION_FAILED,
"Partitioned Topic Name should not contain '-partition-'");
}
}
protected CompletableFuture<Void> validatePartitionedTopicMetadataAsync() {
return pulsar().getBrokerService().fetchPartitionedTopicMetadataAsync(topicName)
.thenAccept(metadata -> {
if (metadata.partitions < 1) {
throw new RestException(Status.CONFLICT, "Topic is not partitioned topic");View on GitHub (pinned to 820761864e)
Solutions
- Use the /admin/v2/non-persistent/... endpoint family for non-persistent topics instead of /admin/v2/persistent/...
- Check the topic URI in your configuration: the domain must be 'persistent' for these endpoints.
- If the topic was intended to be persistent, create/access it with the persistent:// domain prefix.
- Verify client config keys (e.g. topic names in properties/YAML) don't prefix 'non-persistent://'.
Example fix
// before
admin.topics().getStats("non-persistent://my-tenant/my-ns/orders");
// after
admin.topics().getStats("persistent://my-tenant/my-ns/orders"); Defensive patterns
Strategy: validation
Validate before calling
// Java: ensure domain matches the endpoint family
boolean isPersistent(String fq) { return fq.startsWith("persistent://"); }
// only call admin.topics() (persistent endpoints) if isPersistent(fq) Type guard
static String toPersistentUri(String fq) {
return fq.startsWith("non-persistent://")
? fq.replace("non-persistent://", "persistent://") : fq;
} Try / catch
try {
admin.topics().getStats(fqTopic);
} catch (PulsarAdminException e) {
if (e.getStatusCode() == 406) {
// wrong domain: reroute to non-persistent API or fix the URI
}
} Prevention
- Store the topic domain explicitly in config and derive the endpoint family from it.
- Avoid mixing persistent/non-persistent topic URIs in shared config keys.
- Use the admin client's domain-scoped interfaces rather than hand-built REST paths.
When it happens
Trigger: Calling a persistent-topic admin endpoint (e.g. GET /admin/v2/persistent/tenant/ns/topic stats or subscriptions) while passing the topic under a path or with a name resolving to domain non-persistent, e.g. mixing up /admin/v2/persistent/ with a topic that actually is non-persistent://tenant/ns/topic.
Common situations: Applications configured with 'non-persistent' topic URIs but using persistent admin endpoints; copy-paste of topic URIs between persistent and non-persistent sections of admin tooling; clients that omit the scheme and get a default mismatch.
Related errors
- Namespace name is not valid
- Tenant name or namespace is not valid
- Topic name is not valid
- Cannot create topic in system topic format!
- Partitioned Topic Name should not contain '-partition-'
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/71cec5cb8b9f41a7.
Report an issue: GitHub.