apache/pulsar · error · org.apache.pulsar.broker.admin.RestException
domain() invoked from wrong resource
Error message
domain() invoked from wrong resource
What it means
AdminResource.domain() infers the resource domain ('persistent' or 'non-persistent') from the request URI path. If the path does not start with either prefix, the resource was reached from a URL that is not a topic resource, so the broker throws RestException 500 'domain() invoked from wrong resource'. It is an internal invariant check, not a client-input error.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java:105
public abstract class AdminResource extends PulsarWebResource {
protected NamespaceName namespaceName;
protected TopicName topicName;
protected BookKeeper bookKeeper() {
return pulsar().getBookKeeperClient();
}
/**
* Get the domain of the topic (whether it's persistent or non-persistent).
*/
protected String domain() {
if (uri.getPath().startsWith("persistent/")) {
return "persistent";
} else if (uri.getPath().startsWith("non-persistent/")) {
return "non-persistent";
} else {
throw new RestException(Status.INTERNAL_SERVER_ERROR, "domain() invoked from wrong resource");
}
}
// This is a stub method for Mockito
@Override
public void validateSuperUserAccess() {
super.validateSuperUserAccess();
}
// This is a stub method for Mockito
@Override
protected void validateAdminAccessForTenant(String tenant) {
super.validateAdminAccessForTenant(tenant);
}
// This is a stub method for Mockito
@Override
protected boolean isLeaderBroker() {View on GitHub (pinned to 820761864e)
Solutions
- Ensure the request path is a full topic path: /admin/v2/{domain}/{tenant}/{namespace}/{topic} with domain = persistent or non-persistent.
- If implementing a custom resource, do not call validateTopicName/domain() from non-topic resources; use the appropriate namespace/tenant validators instead.
- Check reverse-proxy rewrite rules that may be mangling the URL path.
- If triggered by a Pulsar bug, file an issue with the full request path.
Example fix
// before (custom resource) validateTopicName(property, namespace, topic); // path is /admin/v2/namespaces/..., domain() fails // after validateNamespaceName(property, namespace); // use the matching validator for the resource type
Defensive patterns
Strategy: try-catch
Validate before calling
String path = uri.getPath();
if (!path.startsWith("persistent/") && !path.startsWith("non-persistent/")) {
throw new IllegalStateException("Topic validation requires a persistent/non-persistent topic path");
} Type guard
boolean isTopicResourcePath(String path) {
return path != null && (path.startsWith("persistent/") || path.startsWith("non-persistent/"));
} Try / catch
try {
validateTopicName(tenant, namespace, topic);
} catch (RestException e) {
if (e.getResponse().getStatus() == 500 && e.getMessage().contains("domain() invoked from wrong resource")) {
log.error("Wrong resource type for topic validation; check the request path");
}
} Prevention
- Use full /admin/v2/{persistent|non-persistent}/... topic paths
- Match the validator (tenant/namespace/topic) to the resource type in custom resources
- Audit proxy rewrite rules that could strip the domain prefix
When it happens
Trigger: Calling a topic-validation code path (e.g. an endpoint that ends up calling validateTopicName -> domain()) through an admin URL whose path does not begin with 'persistent/' or 'non-persistent/', such as invoking topic-only logic from a namespace- or tenant-scoped resource, or a mis-routed/mistyped custom endpoint.
Common situations: Bugs in custom admin plugins or forked REST resources that reuse AdminResource topic-validation on non-topic paths; proxy/rewrite rules that strip the 'persistent/'/'non-persistent/' prefix from the URI; calling validateTopicName outside a proper topic request context (e.g. in tests with a fake URI).
Related errors
- Topic does not exist
- Label name cannot be null or empty
- Broker is forbidden to do read-write operations
- Namespace name is not valid
- Tenant name or namespace is not valid
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b06bc8a20bfea11c.
Report an issue: GitHub.