apache/pulsar · warning · RestException

Can't find owner for topic %s

Error message

Can't find owner for topic %s

What it means

validateTopicOwnershipAsync wraps the whole lookup+ownership chain in exceptionally: if the failure cause is an IllegalArgumentException or IllegalStateException (e.g. malformed topic name, invalid namespace/bundle state, service unit already being handled), it is converted to a 412 PRECONDITION_FAILED 'Can't find owner for topic <topic>'. It masks the underlying deterministic problem with a generic 'can't find owner' message.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java:759

                ).thenAccept(pair -> {
                    LookupResult lookupResult = pair.getLeft();
                    boolean isTopicOwned = pair.getRight();

                    if (!isTopicOwned) {
                        boolean newAuthoritative = isLeaderBroker(pulsar());
                        URI redirect = lookupResult.toRedirectUri(uri.getRequestUri(), newAuthoritative);
                        // Redirect
                        log.debug()
                                .attr("redirect", redirect)
                                .log("Redirecting the rest call");
                        throw new WebApplicationException(
                                Response.temporaryRedirect(redirect).build());
                    }
                }).exceptionally(ex -> {
                    if (ex.getCause() instanceof IllegalArgumentException
                            || ex.getCause() instanceof IllegalStateException) {
                            log.debug().attr("topic", topicName).exception(ex).log("Failed to find owner for topic");
                                                throw new RestException(Status.PRECONDITION_FAILED,
                                                        "Can't find owner for topic "
                                                        + topicName);
                    } else if (ex.getCause() instanceof WebApplicationException) {
                        throw (WebApplicationException) ex.getCause();
                    } else {
                        throw new RestException(ex.getCause());
                    }
                });
    }

    /**
     * If the namespace is global, validate the following - 1. If replicated clusters are configured for this global
     * namespace 2. If local cluster belonging to this namespace is replicated 3. If replication is enabled for this
     * namespace <br/>
     * It validates if local cluster is part of replication-cluster. If local cluster is not part of the replication
     * cluster then it redirects request to peer-cluster if any of the peer-cluster is part of replication-cluster of
     * this namespace. If none of the cluster is part of the replication cluster then it fails the validation.
     *

View on GitHub (pinned to 820761864e)

Solutions

  1. Validate the topic's full name format (persistent://tenant/namespace/topic or tenant/namespace/topic) before calling the API
  2. Check broker logs at DEBUG for 'Failed to find owner for topic' with the wrapped exception to see the real cause
  3. Confirm the namespace exists and its bundles are loaded (pulsar-admin namespaces get-bundles)
  4. If caused by transient state during failover, retry once ownership is stable

Example fix

// before
curl .../admin/v2/persistent/my-tenant/ns/topic-
// after (valid topic name)
curl .../admin/v2/persistent/my-tenant/ns/topic-0
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate topic name format before the API call
boolean validTopicName(String t) {
    String noScheme = t.replaceFirst("^(persistent|non-persistent)://", "");
    String[] p = noScheme.split("/");
    return p.length == 3 && !p[0].isEmpty() && !p[1].isEmpty() && !p[2].isEmpty();
}

Try / catch

try {
    admin.topics().getStats(topic);
} catch (PulsarAdminException.PreconditionFailedException e) {
    if (e.getMessage().startsWith("Can't find owner for topic")) {
        // deterministic cause (bad name / invalid state): fix input, do not blind-retry
        checkBrokerDebugLogsForWrappedCause();
    } else throw e;
}

Prevention

When it happens

Trigger: Any topic admin call whose lookup chain throws IllegalArgumentException (bad topic/namespace name format, invalid partition index) or IllegalStateException (invalid state during ownership/redirect) — the exceptionally block at the end of validateTopicOwnershipAsync rethrows as PRECONDITION_FAILED.

Common situations: Malformed topic names passed to the REST API (wrong punctuation, empty namespace, bad partition suffix); namespace deleted concurrently with lookup; broker-side state machine issues after failover; old client/REST paths sending legacy topic name formats to a newer broker.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/acba387cb666f256. Report an issue: GitHub.