apache/pulsar · error · RestException

Termination of a non-persistent topic is not allowed

Error message

Termination of a non-persistent topic is not allowed

What it means

internalTerminateAsync rejects termination of non-persistent topics (405): termination means permanently stopping a persistent managed ledger and returning its last message id, which is meaningless for non-persistent topics.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java:4000

        if (SystemTopicNames.isSystemTopic(topicName)) {
            return FutureUtil.failedFuture(new RestException(Status.METHOD_NOT_ALLOWED,
                    "Termination of a system topic is not allowed"));
        }

        return validateTopicOperationAsync(topicName, TopicOperation.TERMINATE)
        .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(namespaceName))
        .thenCompose(__ -> validateTopicOwnershipAsync(topicName, authoritative))
        .thenCompose(__ -> getPartitionedTopicMetadataAsync(topicName, authoritative, false))
        .thenAccept(partitionMetadata -> {
            if (partitionMetadata.partitions > 0) {
                throw new RestException(Status.METHOD_NOT_ALLOWED,
                        "Termination of a partitioned topic is not allowed");
            }
        })
        .thenCompose(__ -> getTopicReferenceAsync(topicName))
        .thenCompose(topic -> {
            if (!(topic instanceof PersistentTopic)) {
                throw new RestException(Status.METHOD_NOT_ALLOWED,
                        "Termination of a non-persistent topic is not allowed");
            }
            return ((PersistentTopic) topic).terminate();
        });
    }

    protected void internalTerminatePartitionedTopic(AsyncResponse asyncResponse, boolean authoritative) {
        if (topicName.isPartitioned()) {
            String msg = "Termination of a non-partitioned topic is not allowed using partitioned-terminate"
                    + ", please use terminate commands";
            log.error().attr("topic", topicName).attr("msg", msg).log("");
            asyncResponse.resume(new RestException(Status.METHOD_NOT_ALLOWED, msg));
            return;
        }
        validateTopicOperationAsync(topicName, TopicOperation.TERMINATE)
        .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(namespaceName))
        .thenCompose(unused -> getPartitionedTopicMetadataAsync(topicName, authoritative, false))
        .thenAccept(partitionMetadata -> {

View on GitHub (pinned to 820761864e)

Solutions

  1. Delete the non-persistent topic instead of terminating it
  2. Switch to a persistent topic if termination semantics are required
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java:4000 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/d466792e3990178e. Report an issue: GitHub.