apache/pulsar · warning · RestException
GetMessageById is not allowed on partitioned-topic
Error message
GetMessageById is not allowed on partitioned-topic
What it means
The getMessageById admin REST operation refuses to run on a partitioned topic's base name. A message ID (ledgerId/entryId) is only meaningful within a single persistent backing topic (a partition), so the broker cannot look up a message by ID across all partitions. It is raised as 405 METHOD_NOT_ALLOWED after the partitioned-topic metadata check.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java:2951
seekPosition = isExcluded ? seekPosition.getNext() : seekPosition;
}
return seekPosition;
}
protected CompletableFuture<Response> internalGetMessageById(long ledgerId, long entryId, boolean authoritative) {
return validateTopicOperationAsync(topicName, TopicOperation.PEEK_MESSAGES)
.thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(namespaceName))
.thenCompose(__ -> {
if (topicName.isPartitioned()) {
return CompletableFuture.completedFuture(null);
} else {
return getPartitionedTopicMetadataAsync(topicName, authoritative, false)
.thenAccept(topicMetadata -> {
if (topicMetadata.partitions > 0) {
log.warn()
.attr("topic", topicName)
.log("Not supported getMessageById operation on partitioned-topic");
throw new RestException(Status.METHOD_NOT_ALLOWED,
"GetMessageById is not allowed on partitioned-topic");
}
});
}
}).thenCompose(ignore -> validateTopicOwnershipAsync(topicName, authoritative))
.thenCompose(__ -> getTopicReferenceAsync(topicName))
.thenCompose(topic -> {
CompletableFuture<Response> results = new CompletableFuture<>();
ManagedLedger ledger = ((PersistentTopic) topic).getManagedLedger();
ledger.asyncReadEntry(PositionFactory.create(ledgerId, entryId),
new AsyncCallbacks.ReadEntryCallback() {
@Override
public void readEntryFailed(ManagedLedgerException exception,
Object ctx) {
if (exception instanceof ManagedLedgerException.LedgerNotExistException) {
results.completeExceptionally(
new RestException(Status.NOT_FOUND, "Message id not found"));
return;View on GitHub (pinned to 820761864e)
Solutions
- Determine which partition owns the ledger and call the endpoint with that partition name (my-topic-partition-N)
- If the partition is unknown, iterate all partitions and try getMessageById on each
- Avoid the ambiguity by persisting the full partition topic name alongside any message ID
Example fix
// before
String msg = admin.topics().getMessageById("persistent://public/default/my-topic", ledgerId, entryId);
// after
String msg = admin.topics().getMessageById("persistent://public/default/my-topic-partition-0", ledgerId, entryId); Defensive patterns
Strategy: validation
Validate before calling
PartitionedTopicMetadata md = admin.topics().getPartitionedMetadata(topic);
if (md.partitions > 0) throw new IllegalArgumentException("getMessageById requires a partition topic name"); Type guard
boolean isPartitionName(String topic) { return topic.matches(".*-partition-\\d+$"); } Try / catch
try { admin.topics().getMessageById(topic, ledgerId, entryId); }
catch (PulsarAdminException e) {
if (e.getStatusCode() == 405) { /* retry on partitions */ }
} Prevention
- Record the exact partition topic name with every ledgerId/entryId
- If only the base name is known, iterate partitions when looking up by ID
When it happens
Trigger: GET /admin/v2/persistent/{tenant}/{namespace}/{topic}/ledger/{ledgerId}/entry/{entryId} with the partitioned topic's base name; the metadata check sees partitions > 0 and throws before ownership validation.
Common situations: Copying a ledgerId/entryId from broker logs and trying to fetch it via the partitioned topic name; debugging tools that accept a topic URL but don't resolve partitions.
Related errors
- Reset-cursor at position is not allowed for partitioned-topi
- Get message ID by timestamp on a partitioned topic is not al
- Peek messages on a partitioned topic is not allowed
- Examine messages on a partitioned topic is not allowed, plea
- Get message ID by timestamp on a non-persistent topic is not
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/3ad4da8f826e7cac.
Report an issue: GitHub.