apache/pulsar · warning · RestException

Peek messages on a partitioned topic is not allowed

Error message

Peek messages on a partitioned topic is not allowed

What it means

Peek/preview of messages (peekNthMessage via the admin REST examine/peek endpoints) is only valid on an individual partition, since entries live in that partition's managed ledger. For a partitioned topic base name with partitions > 0 the broker throws 405 METHOD_NOT_ALLOWED 'Peek messages on a partitioned topic is not allowed'. The check is skipped when the name already refers to a partition.

Source

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

            if (position == null) {
                return null;
            } else {
                return new MessageIdImpl(position.getLedgerId(), position.getEntryId(),
                    topicName.getPartitionIndex());
            }
        });
    }

    protected CompletableFuture<Response> internalPeekNthMessageAsync(String subName, int messagePosition,
                                                                      boolean authoritative) {
        return validateTopicOperationAsync(topicName, TopicOperation.PEEK_MESSAGES, subName)
        .thenCompose(__ -> {
            // If the topic name is a partition name, no need to get partition topic metadata again
            if (!topicName.isPartitioned()) {
                return getPartitionedTopicMetadataAsync(topicName, authoritative, false)
                        .thenCompose(topicMetadata -> {
                            if (topicMetadata.partitions > 0) {
                                throw new RestException(Status.METHOD_NOT_ALLOWED,
                                        "Peek messages on a partitioned topic is not allowed");
                            }
                            return CompletableFuture.completedFuture(null);
                        });
            } else {
                return CompletableFuture.completedFuture(null);
            }
        }).thenCompose(__ -> validateTopicOwnershipAsync(topicName, authoritative))
        .thenCompose(__ -> getTopicReferenceAsync(topicName))
        .thenCompose(topic -> {
            CompletableFuture<Entry> entry;
            if (!(topic instanceof PersistentTopic)) {
                log.error()
                        .attr("topic", topicName)
                        .attr("subscription", subName)
                        .log("Not supported operation of non-persistent topic");
                throw new RestException(Status.METHOD_NOT_ALLOWED,
                        "Peek messages on a non-persistent topic is not allowed");

View on GitHub (pinned to 820761864e)

Solutions

  1. Peek on a concrete partition: replace my-topic with my-topic-partition-N
  2. Enumerate partitions first via the partitions endpoint and peek each as needed
  3. Use the consumer-level receive/peek client API if you need cross-partition message visibility

Example fix

// before
Messages msg = admin.topics().peekMessages("persistent://public/default/my-topic", "my-sub", 1);
// after
Messages msg = admin.topics().peekMessages("persistent://public/default/my-topic-partition-0", "my-sub", 1);
Defensive patterns

Strategy: validation

Validate before calling

PartitionedTopicMetadata md = admin.topics().getPartitionedMetadata(topic);
if (md.partitions > 0) throw new IllegalArgumentException("Peek a specific partition");

Type guard

boolean isPartitionName(String topic) { return topic.matches(".*-partition-\\d+$"); }

Try / catch

try { admin.topics().peekMessages(topic, sub, n); }
catch (PulsarAdminException e) { if (e.getStatusCode() == 405) { /* use partitions */ } }

Prevention

When it happens

Trigger: GET /admin/v2/persistent/{tenant}/{namespace}/{topic}/subscription/{sub}/position/{messagePosition} (peek) with a partitioned topic base name; also internal peekNthMessage paths after the metadata check.

Common situations: Debugging subscriptions on a partitioned topic and forgetting that peek needs the -partition-N suffix; admin consoles listing topics by base name.

Related errors


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