This is an automated email from the ASF dual-hosted git repository. lhotari pushed a commit to branch branch-4.0 in repository https://gitbox.apache.org/repos/asf/pulsar.git
commit a94a4c5a0e2ed3c6f5e2ca70b1079fffd361c707 Author: Lari Hotari <[email protected]> AuthorDate: Fri Jul 3 02:57:11 2026 +0300 [fix][broker][branch-4.0] Fix NOT_FOUND for topic policy operations on idle non-persistent topics ### Motivation On branch-4.0, topic-level policy admin operations run `PersistentTopicsBase#preValidation`, which checks topic existence via `AdminResource#checkTopicExistsAsync`. For non-persistent topics that check lists topics through `NamespaceService#getListOfNonPersistentTopics`, which only returns "active" non-persistent topics (those with producers, consumers or subscriptions). A freshly created or otherwise idle non-persistent topic has none of these, so it was reported as non-existent and the operation failed with `404 NOT_FOUND` -- for example `admin.topicPolicies().setMaxSubscriptionsPerTopic(topic, 10)` immediately after `admin.topics().createNonPartitionedTopic(topic)`. This is branch-4.0 specific. On master and branch-4.2 it is already fixed by #24225 ("Allow recreation of partitioned topic after metadata loss"), which rewrote `checkTopicExistsAsync` to delegate to `NamespaceService#checkTopicExistsAsync`. #24225 was never backported to branch-4.0. Surfaced by `TopicPoliciesTest#testNonPersistentTopicAppliesTopicPolicyOnLoad` (added by #26134), which fails on branch-4.0 but passes on master/branch-4.2. ### Modifications In `AdminResource#checkTopicExistsAsync`, resolve non-persistent topic existence through `NamespaceService#checkTopicExistsAsync`, which detects a loaded non-persistent topic via the owner broker's in-memory topic map (no "active" filter). Persistent-topic handling is unchanged. --- .../java/org/apache/pulsar/broker/admin/AdminResource.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java index dd45ac3c94c..03fa76e48bf 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java @@ -748,6 +748,20 @@ public abstract class AdminResource extends PulsarWebResource { * @param topicName given topic name */ protected CompletableFuture<Boolean> checkTopicExistsAsync(TopicName topicName) { + if (!topicName.isPersistent()) { + // For non-persistent topics, resolve existence via NamespaceService#checkTopicExistsAsync, which + // consults the owner broker's in-memory topic map. The list-based path below (getListOfTopics -> + // getListOfNonPersistentTopics) only reports "active" non-persistent topics -- those with producers, + // consumers or subscriptions -- so an idle non-persistent topic (e.g. just created) would be treated + // as non-existent, making its topic-policy admin operations fail with 404 NOT_FOUND. + // branch-4.0-only workaround; branch-4.1+ fix this via apache/pulsar#24225, not backported to branch-4.0. + return pulsar().getNamespaceService().checkTopicExistsAsync(topicName).thenApply(topicExistsInfo -> { + boolean exists = topicExistsInfo.isExists(); + topicExistsInfo.recycle(); + return exists; + }); + } + return pulsar().getNamespaceService().getListOfTopics(topicName.getNamespaceObject(), CommandGetTopicsOfNamespace.Mode.ALL) .thenCompose(topics -> {
