{"record":{"id":"74c5b0ebfc410b8e","repo":"apache/pulsar","slug":"examine-messages-on-a-non-persistent-topic-is-not","errorCode":null,"errorMessage":"Examine messages on a non-persistent topic is not allowed","messagePattern":"Examine messages on a non-persistent topic is not allowed","errorType":"http","errorClass":"RestException","httpStatus":405,"severity":"warning","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java","lineNumber":3154,"sourceCode":"                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 {\n                PersistentTopic persistentTopic = (PersistentTopic) topic;\n                long totalMessage = persistentTopic.getNumberOfEntries();\n                if (totalMessage <= 0) {\n                    throw new RestException(Status.PRECONDITION_FAILED,\n                            \"Could not examine messages due to the total message is zero\");\n                }\n                Position startPosition = persistentTopic.getFirstPosition();\n\n                long messageToSkip = initialPositionLocal.equals(\"earliest\") ? messagePositionLocal :\n                        totalMessage - messagePositionLocal + 1;\n                CompletableFuture<Entry> future = new CompletableFuture<>();\n                Position readPosition = persistentTopic.getPositionAfterN(startPosition, messageToSkip);\n                persistentTopic.asyncReadEntry(readPosition, new AsyncCallbacks.ReadEntryCallback() {\n                    @Override\n                    public void readEntryComplete(Entry entry, Object ctx) {","sourceCodeStart":3136,"sourceCodeEnd":3172,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java#L3136-L3172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Examine only persistent topics; filter out non-persistent:// topics in tooling","If examination of message flow is needed for non-persistent topics, attach a reader/consumer instead","Verify the topic's domain in its full URL before invoking examine"],"exampleFix":"// before\nadmin.topics().examineMessages(\"non-persistent://public/default/my-topic\");\n// after\nif (topicName.startsWith(\"persistent://\")) { admin.topics().examineMessages(topicName); }","handlingStrategy":"validation","validationCode":"if (!topic.startsWith(\"persistent://\")) {\n    throw new IllegalArgumentException(\"Examine requires a persistent topic\");\n}","typeGuard":"boolean isPersistentTopic(String topic) { return topic.startsWith(\"persistent://\"); }","tryCatchPattern":null,"preventionTips":["Filter out non-persistent topics before bulk examination","Use consumer/reader APIs to validate non-persistent topic health instead"],"tags":["rest-api","non-persistent-topic","method-not-allowed","admin"],"backgroundTag":"operation-not-supported-on-non-persistent-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"}