{"record":{"id":"81ac3bfea46aff62","repo":"apache/pulsar","slug":"failed-to-find-ownership-for-topic-s","errorCode":null,"errorMessage":"Failed to find ownership for topic:%s","messagePattern":"Failed to find ownership for topic:(.+?)","errorType":"http","errorClass":"RestException","httpStatus":412,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java","lineNumber":736,"sourceCode":"     */\n    protected void validateTopicOwnership(TopicName topicName, boolean authoritative) {\n        sync(()-> validateTopicOwnershipAsync(topicName, authoritative));\n    }\n\n    protected CompletableFuture<Void> validateTopicOwnershipAsync(TopicName topicName, boolean authoritative) {\n        NamespaceService nsService = pulsar().getNamespaceService();\n\n        LookupOptions options = LookupOptions.builder()\n                .authoritative(authoritative)\n                .webServiceAdvertisedListenerName(getWebServiceListenerName())\n                .readOnly(false)\n                .build();\n\n        return nsService.getLookupResultForWebRequestAsync(topicName, options)\n                .thenApply(optLookupResult ->\n                        optLookupResult.orElseThrow(() -> {\n                            log.info(\"Unable to get web service url\");\n                            throw new RestException(Status.PRECONDITION_FAILED,\n                                    \"Failed to find ownership for topic:\" + topicName);\n                        })\n                ).thenCompose(lookupResult -> nsService.isServiceUnitOwnedAsync(topicName)\n                        .thenApply(isTopicOwned -> Pair.of(lookupResult, isTopicOwned))\n                ).thenAccept(pair -> {\n                    LookupResult lookupResult = pair.getLeft();\n                    boolean isTopicOwned = pair.getRight();\n\n                    if (!isTopicOwned) {\n                        boolean newAuthoritative = isLeaderBroker(pulsar());\n                        URI redirect = lookupResult.toRedirectUri(uri.getRequestUri(), newAuthoritative);\n                        // Redirect\n                        log.debug()\n                                .attr(\"redirect\", redirect)\n                                .log(\"Redirecting the rest call\");\n                        throw new WebApplicationException(\n                                Response.temporaryRedirect(redirect).build());\n                    }","sourceCodeStart":718,"sourceCodeEnd":754,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java#L718-L754","documentation":"validateTopicOwnershipAsync performs a topic lookup; if the lookup returns no result (no broker owns or could acquire the topic), it throws 412 PRECONDITION_FAILED 'Failed to find ownership for topic:...'. With readOnly=false the broker normally tries to acquire ownership, so an empty lookup signals lookup/registration failure rather than a benign 'not owned yet'.","triggerScenarios":"Admin REST calls on a topic (stats, terminate, delete, permissions) when getLookupResultForWebRequestAsync yields empty Optional — topic's namespace bundle has no owning broker, broker registration missing, or the advertised web service URL can't be produced.","commonSituations":"Right after broker restart or namespace unload when ownership isn't established; cluster with no live brokers; advertised listeners/service URL misconfiguration; partitions whose parent topic's bundle is being migrated; client hitting a broker that isn't in the same cluster as the topic's owner.","solutions":["Retry after a short delay so a broker can acquire the topic's bundle","Confirm brokers are alive and registered (pulsar-admin brokers list)","Check advertisedAddress/webservicePort/listener config if logs show 'Unable to get web service url'","Let the broker redirect: follow the 307 Temporary Redirect responses rather than forcing requests to a fixed broker"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Verify brokers are registered and the topic exists before ownership-sensitive admin calls\nif (admin.brokers().getActiveBrokers().length == 0) throw new IllegalStateException(\"no brokers\");\nadmin.namespaces().getTopics(ns); // confirms namespace served; topic existence check for non-partitioned","typeGuard":null,"tryCatchPattern":"try {\n    admin.topics().getStats(topic);\n} catch (PulsarAdminException.PreconditionFailedException e) {\n    if (e.getMessage().startsWith(\"Failed to find ownership for topic\")) {\n        retryWithBackoff(() -> admin.topics().getStats(topic), 3);\n    } else throw e;\n}","preventionTips":["Follow HTTP 307 redirects from the admin API instead of pinning a broker","Retry with backoff after broker restarts/failovers","Ensure advertisedAddress and listener web service URLs are correct cluster-wide"],"tags":["http-412","topic","ownership","lookup"],"backgroundTag":"no-owner-for-service-unit","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"}