apache/pulsar · warning · RestException
Topic name is not valid
Error message
Topic name is not valid
What it means
HTTP 412 PRECONDITION_FAILED from validateTopicName: the encoded topic string supplied to a transaction admin endpoint could not be parsed into a valid topic (CompleteTopicName/TopicName parsing threw). The broker logs 'Failed to validate topic name' with tenant/namespace/topic details.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TransactionsBase.java:541
throw new RestException(SERVICE_UNAVAILABLE,
"This Broker is not configured with transactionCoordinatorEnabled=true.");
}
}
protected void validateTopicName(String tenant, String namespace, String encodedTopic) {
String topic = Codec.decode(encodedTopic);
try {
this.namespaceName = NamespaceName.get(tenant, namespace);
this.topicName = TopicName.get(TopicDomain.persistent.toString(), namespaceName, topic);
} catch (IllegalArgumentException e) {
log.warn()
.attr("domain", domain())
.attr("tenant", tenant)
.attr("namespace", namespace)
.attr("topic", topic)
.exception(e)
.log("Failed to validate topic name");
throw new RestException(Response.Status.PRECONDITION_FAILED, "Topic name is not valid");
}
}
protected CompletableFuture<Void> internalScaleTransactionCoordinators(int replicas) {
return validateSuperUserAccessAsync()
.thenCompose((ignore) -> namespaceResources().getPartitionedTopicResources()
.updatePartitionedTopicAsync(SystemTopicNames.TRANSACTION_COORDINATOR_ASSIGN, p -> {
if (p.partitions >= replicas) {
throw new RestException(Response.Status.NOT_ACCEPTABLE,
"Number of transaction coordinators should "
+ "be more than the current number of transaction coordinator");
}
return new PartitionedTopicMetadata(replicas);
}));
}
protected CompletableFuture<PositionInPendingAckStats> internalGetPositionStatsPendingAckStats(
boolean authoritative, String subName, Position position, Integer batchIndex) {View on GitHub (pinned to 820761864e)
Solutions
- Use the fully qualified topic name: persistent://tenant/namespace/topic (or non-persistent://...), URL-encoded when in a path.
- Validate the topic name with TopicName.get(topic) client-side or org.apache.pulsar.common.naming utilities before calling the API.
- Check for encoding problems: encode '/' as %2F if the endpoint expects a single path segment, or use the query/REST variant that takes separate tenant/ns/topic.
- Remove any partition suffix if the endpoint expects the base topic, or add it if it expects the specific partition.
Example fix
// before
String topic = "my-topic"; // not fully qualified
admin.transactions().getPendingAckStats("tenant", "ns", topic);
// after
String topic = "persistent://tenant/ns/my-topic";
admin.transactions().getPendingAckStats("tenant", "ns", topic); Defensive patterns
Strategy: validation
Validate before calling
import org.apache.pulsar.common.naming.TopicName;
static boolean isValidTopicName(String topic) {
try {
TopicName.get(topic);
return true;
} catch (Exception e) {
return false;
}
}
// use: isValidTopicName("persistent://tenant/ns/my-topic") Type guard
static boolean isFullyQualifiedTopic(String topic) {
return topic != null && (topic.startsWith("persistent://") || topic.startsWith("non-persistent://"))
&& topic.split("://", 2)[1].split("/").length >= 3;
} Try / catch
try {
admin.transactions().getPendingAckStats(tenant, ns, topic);
} catch (PulsarAdminException e) {
if (e.getStatusCode() == 412 && e.getMessage().contains("Topic name is not valid")) {
String fqTopic = "persistent://" + tenant + "/" + ns + "/" + topic.replaceFirst("^persistent://[^/]+/[^/]+/", "");
// retry with fully qualified, URL-encoded name
} else {
throw e;
}
} Prevention
- Always pass fully qualified persistent://tenant/namespace/topic names to transaction admin APIs.
- URL-encode topic parameters when embedding them in REST paths.
- Validate with TopicName.get() (org.apache.pulsar.common.naming) before calling the API.
- Watch for accidental partition suffixes like -partition-0 in the topic argument.
When it happens
Trigger: Transaction admin calls (e.g. transaction pending-ack stats, coordinator endpoints taking a topic parameter) where the topic argument is malformed: missing persistent/non-persistent domain, missing local-name, bad tenant/namespace segment, or not URL-encoded special characters.
Common situations: Passing a short topic name (topic-only) where a fully-qualified persistent://tenant/namespace/topic is expected; URL-encoding issues with '/' in path parameters; partitioned vs non-partitioned confusion (appending -partition-N); mixing up tenants/namespaces in the topic string.
Related errors
- Topic name is not valid
- cluster data is required
- Peer cluster ${peerCluster} does not exist
- Cluster ${cluster} does not exist.
- ClusterIds should not be null or empty
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b8d2cee42d957778.
Report an issue: GitHub.