apache/pulsar · error · RestException
Client is not authorized to perform operation
Error message
Client is not authorized to perform operation
What it means
registerSink catches PulsarAdminException.NotAuthorizedException raised while inspecting the tenant/namespace (getting tenant data or listing namespaces) and rethrows it as a 401 UNAUTHORIZED RestException with this generic message. It means the worker's admin client credentials are not authorized for the target tenant/namespace policies, not necessarily the end user's credentials.
Source
Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java:127
String qualifiedNamespace = tenant + "/" + namespace;
List<String> namespaces = worker().getBrokerAdmin().namespaces().getNamespaces(tenant);
if (namespaces != null && !namespaces.contains(qualifiedNamespace)) {
String qualifiedNamespaceWithCluster = String.format("%s/%s/%s", tenant,
worker().getWorkerConfig().getPulsarFunctionsCluster(), namespace);
if (namespaces != null && !namespaces.contains(qualifiedNamespaceWithCluster)) {
log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sinkName)
.attr("namespace3", namespace).log("/ / Namespace does not exist");
throw new RestException(Response.Status.BAD_REQUEST, "Namespace does not exist");
}
}
} catch (PulsarAdminException.NotAuthorizedException e) {
log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sinkName)
.attr("componentType", ComponentTypeUtils.toString(componentType))
.log("/ / Client is not authorized to operate on tenant");
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
} catch (PulsarAdminException.NotFoundException e) {
log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sinkName)
.attr("tenant3", tenant).log("/ / Tenant does not exist");
throw new RestException(Response.Status.BAD_REQUEST, "Tenant does not exist");
} catch (PulsarAdminException e) {
log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sinkName)
.exception(e).log("/ / Issues getting tenant data");
throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
}
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
if (functionMetaDataManager.containsFunction(tenant, namespace, sinkName)) {
log.error().attr("componentType", ComponentTypeUtils.toString(componentType)).attr("tenant", tenant)
.attr("namespace", namespace).attr("componentName", sinkName).log("/ / already exists");View on GitHub (pinned to 820761864e)
Solutions
- Grant the worker's role tenant admin rights: pulsar-admin tenants update tenant --admin-roles <worker-role>.
- Check namespace policies: pulsar-admin namespaces grant-permission tenant/ns --actions functions,sinks --role <worker-role>.
- Verify the worker's authentication plugin/parameters and that its token maps to the intended role.
- Inspect broker authorization logs to see which role/action was denied.
Example fix
// before: worker role not authorized tenants.update(tenant, new TenantInfoImpl(Collections.emptySet(), Collections.emptySet())); // after: include the worker role as tenant admin pulsar-admin tenants update my-tenant --admin-roles functions-worker-role
Defensive patterns
Strategy: try-catch
Validate before calling
// verify authorization up front admin.tenants().getTenantInfo(tenant); // throws NotAuthorizedException if the worker role lacks access admin.namespaces().getPermissions(tenant + "/" + namespace);
Try / catch
try {
sinks.registerSink(tenant, ns, name, cfg, null, null, null, authParams);
} catch (RestException e) {
if (e.getResponse().getStatus() == 401) {
// grant the worker role tenant admin / namespace functions+sinks permissions
} else { throw e; }
} Prevention
- Add the functions worker role to every tenant's adminRoles at tenant creation time
- Keep worker auth token/key provisioning in infrastructure-as-code
- Test authorization by running an admin op as the worker role before deploying sinks
When it happens
Trigger: registerSink where the worker's PulsarAdmin session lacks admin/tenant permissions: the worker's principal is not listed in the tenant adminRoles, namespace policies deny the role, or authorization is enabled and the worker role has no functions/sinks permissions on the namespace.
Common situations: Kubernetes deployments where the worker's auth token role was never granted on the tenant; enabling authorization on an existing cluster without updating tenant admin roles; wrong token/key file mounted for the functions worker.
Related errors
- Unauthorized to validateBothTenantOperationAndSuperUser for
- Invalid broker configuration. Authentication must be enabled
- Unauthorized to validateBothSuperuserAndClusterOperation for
- Unauthorized to validateBothSuperuserAndClusterPolicyOperati
- Unauthorized to validateClusterOperation for originalPrincip
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/022360f7acde8306.
Report an issue: GitHub.