{"record":{"id":"f6aeadab307c762d","repo":"apache/pulsar","slug":"examine-messages-on-a-partitioned-topic-is-not-all","errorCode":null,"errorMessage":"Examine messages on a partitioned topic is not allowed, please try examine message on specific topic partition","messagePattern":"Examine messages on a partitioned topic is not allowed, please try examine message on specific topic partition","errorType":"http","errorClass":"RestException","httpStatus":405,"severity":"warning","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java","lineNumber":3139,"sourceCode":"                    entry.release();\n                }\n            }\n        });\n    }\n\n    protected CompletableFuture<Response> internalExamineMessageAsync(String initialPosition, long messagePosition,\n                                                                      boolean authoritative) {\n        long messagePositionLocal = messagePosition < 1 ? 1 : messagePosition;\n        String initialPositionLocal = initialPosition == null ? \"latest\" : initialPosition;\n        return validateTopicOperationAsync(topicName, TopicOperation.PEEK_MESSAGES)\n        .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(namespaceName))\n        .thenCompose(__ -> validateTopicOwnershipAsync(topicName, authoritative))\n        .thenCompose(__ -> {\n            if (!topicName.isPartitioned()) {\n                return getPartitionedTopicMetadataAsync(topicName, authoritative, false)\n                        .thenCompose(partitionedTopicMetadata -> {\n                            if (partitionedTopicMetadata.partitions > 0) {\n                                throw new RestException(Status.METHOD_NOT_ALLOWED,\n                                        \"Examine messages on a partitioned topic is not allowed, \"\n                                                + \"please try examine message on specific topic partition\");\n                            } else {\n                                return CompletableFuture.completedFuture(null);\n                            }\n                        });\n            }\n            return CompletableFuture.completedFuture(null);\n        }).thenCompose(__ -> getTopicReferenceAsync(topicName))\n        .thenCompose(topic -> {\n            if (!(topic instanceof PersistentTopic)) {\n                log.error()\n                        .attr(\"topic\", topicName)\n                        .log(\"Not supported operation of non-persistent topic\");\n                throw new RestException(Status.METHOD_NOT_ALLOWED,\n                        \"Examine messages on a non-persistent topic is not allowed\");\n            }\n            try {","sourceCodeStart":3121,"sourceCodeEnd":3157,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java#L3121-L3157","documentation":"The 'examine messages' admin operation (verifies a topic's latest messages can be read) does not work on a partitioned topic's base name; examination applies per partition. If the topic name is not already a partition and metadata shows partitions > 0, the broker throws 405 METHOD_NOT_ALLOWED with this message.","triggerScenarios":"GET /admin/v2/persistent/{tenant}/{namespace}/{topic}/examinemessages (or examineMessages call) with a partitioned topic base name instead of my-topic-partition-N.","commonSituations":"CI health checks that enumerate partitioned topics by base name; operators running examine across a namespace without resolving partitions.","solutions":["Run examine on each concrete partition (my-topic-partition-N)","Enumerate partitions via the partitions endpoint and loop examine calls per partition","Skip partitioned base names in bulk examine tooling, or expand them to partitions first"],"exampleFix":"// before\nadmin.topics().examineMessages(\"persistent://public/default/my-topic\");\n// after\nfor (String part : admin.topics().getPartitionedPartitions(\"persistent://public/default/my-topic\")) {\n    admin.topics().examineMessages(part);\n}","handlingStrategy":"validation","validationCode":"PartitionedTopicMetadata md = admin.topics().getPartitionedMetadata(topic);\nif (md.partitions > 0) { /* examine each partition instead */ }","typeGuard":"boolean isPartitionName(String topic) { return topic.matches(\".*-partition-\\\\d+$\"); }","tryCatchPattern":null,"preventionTips":["Expand partitioned base names into partitions in bulk-examine tooling","Catch 405 and fall back to per-partition examination"],"tags":["rest-api","partitioned-topic","method-not-allowed","admin"],"backgroundTag":"operation-not-supported-on-partitioned-topic","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}