apache/pulsar · error · RestException

Client is not authorized to perform operation

Error message

Client is not authorized to perform operation

What it means

When the worker's lookup of the tenant's namespaces (via PulsarAdmin) is rejected with PulsarAdminException.NotAuthorizedException, registerFunction rethrows it as HTTP 401 'Client is not authorized to perform operation'. The authenticated subject lacks admin/tenant permission to list namespaces on that tenant.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java:128

            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.contains(qualifiedNamespaceWithCluster)) {
                    log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                            .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", functionName)

                    .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", functionName)

                    .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", functionName)

                    .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, functionName)) {
            log.error().attr("componentType", ComponentTypeUtils.toString(componentType)).attr("tenant", tenant)

                    .attr("namespace", namespace).attr("componentName", functionName).log("/ / already exists");

View on GitHub (pinned to 820761864e)

Solutions

  1. Grant the calling role tenant admin/functions permissions: 'pulsar-admin tenants update ... --admin-roles' or namespaces grant-permission
  2. Verify the client credentials (token/Athenz/K8s secret) belong to an authorized role
  3. Check the functions worker's brokerClientAuthenticationPlugin/Parameters are valid so worker-to-broker calls are authorized

Example fix

// before
// role 'fn-user' has no permissions on tenant 'public'
// after
pulsar-admin tenants update public --admin-roles fn-user
# or
pulsar-admin namespaces grant-permission public/default --role fn-user --permissions functions
Defensive patterns

Strategy: try-catch

Validate before calling

try {
    admin.namespaces().getNamespaces(tenant); // probes authorization
} catch (PulsarAdminException.NotAuthorizedException e) {
    throw new IllegalStateException("role lacks permissions on " + tenant, e);
}

Try / catch

try { admin.functions().createFunction(...); }
catch (PulsarAdminException.NotAuthorizedException e) {
    // refresh credentials or grant admin/tenant role, then retry
}

Prevention

When it happens

Trigger: Calling the Functions REST API with credentials that lack tenant admin or functions permissions while authorization is enabled; expired or wrong-role token; worker's brokerClientAuthenticationParameters misconfigured so its internal admin client is unauthorized.

Common situations: Token issued for a role without produce/consume or tenant-admin policy; ACL changes after which the client cache still uses the old role; functions worker superuser misconfiguration; using anonymous access in a secured cluster.

Related errors


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