apache/pulsar · warning · RestException

Examine messages on a non-persistent topic is not allowed

Error message

Examine messages on a non-persistent topic is not allowed

What it means

Examine messages requires a PersistentTopic because it inspects the managed ledger (entry count, last entries). If the topic reference is not PersistentTopic, the broker logs 'Not supported operation of non-persistent topic' and throws 405 METHOD_NOT_ALLOWED with this message.

Source

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

                return getPartitionedTopicMetadataAsync(topicName, authoritative, false)
                        .thenCompose(partitionedTopicMetadata -> {
                            if (partitionedTopicMetadata.partitions > 0) {
                                throw new RestException(Status.METHOD_NOT_ALLOWED,
                                        "Examine messages on a partitioned topic is not allowed, "
                                                + "please try examine message on specific topic partition");
                            } else {
                                return CompletableFuture.completedFuture(null);
                            }
                        });
            }
            return CompletableFuture.completedFuture(null);
        }).thenCompose(__ -> getTopicReferenceAsync(topicName))
        .thenCompose(topic -> {
            if (!(topic instanceof PersistentTopic)) {
                log.error()
                        .attr("topic", topicName)
                        .log("Not supported operation of non-persistent topic");
                throw new RestException(Status.METHOD_NOT_ALLOWED,
                        "Examine messages on a non-persistent topic is not allowed");
            }
            try {
                PersistentTopic persistentTopic = (PersistentTopic) topic;
                long totalMessage = persistentTopic.getNumberOfEntries();
                if (totalMessage <= 0) {
                    throw new RestException(Status.PRECONDITION_FAILED,
                            "Could not examine messages due to the total message is zero");
                }
                Position startPosition = persistentTopic.getFirstPosition();

                long messageToSkip = initialPositionLocal.equals("earliest") ? messagePositionLocal :
                        totalMessage - messagePositionLocal + 1;
                CompletableFuture<Entry> future = new CompletableFuture<>();
                Position readPosition = persistentTopic.getPositionAfterN(startPosition, messageToSkip);
                persistentTopic.asyncReadEntry(readPosition, new AsyncCallbacks.ReadEntryCallback() {
                    @Override
                    public void readEntryComplete(Entry entry, Object ctx) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Examine only persistent topics; filter out non-persistent:// topics in tooling
  2. If examination of message flow is needed for non-persistent topics, attach a reader/consumer instead
  3. Verify the topic's domain in its full URL before invoking examine

Example fix

// before
admin.topics().examineMessages("non-persistent://public/default/my-topic");
// after
if (topicName.startsWith("persistent://")) { admin.topics().examineMessages(topicName); }
Defensive patterns

Strategy: validation

Validate before calling

if (!topic.startsWith("persistent://")) {
    throw new IllegalArgumentException("Examine requires a persistent topic");
}

Type guard

boolean isPersistentTopic(String topic) { return topic.startsWith("persistent://"); }

Prevention

When it happens

Trigger: Calling the examineMessages REST endpoint on a topic under the non-persistent:// domain, or any topic reference failing the instanceof PersistentTopic check after ownership validation.

Common situations: Bulk examination scripts iterating all topics in a namespace that includes non-persistent topics; misconfigured topic domains where a non-persistent topic shares a name with an expected persistent one.

Related errors


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