{"record":{"id":"d4a172acd8b90307","repo":"apache/pulsar","slug":"client-is-not-authorized-to-perform-operation-d4a172","errorCode":null,"errorMessage":"Client is not authorized to perform operation","messagePattern":"Client is not authorized to perform operation","errorType":"http","errorClass":"RestException","httpStatus":401,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java","lineNumber":128,"sourceCode":"            String qualifiedNamespace = tenant + \"/\" + namespace;\n            List<String> namespaces = worker().getBrokerAdmin().namespaces().getNamespaces(tenant);\n            if (namespaces != null && !namespaces.contains(qualifiedNamespace)) {\n                String qualifiedNamespaceWithCluster = String.format(\"%s/%s/%s\", tenant,\n                        worker().getWorkerConfig().getPulsarFunctionsCluster(), namespace);\n                if (!namespaces.contains(qualifiedNamespaceWithCluster)) {\n                    log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                            .attr(\"namespace3\", namespace).log(\"/ / Namespace does not exist\");\n                    throw new RestException(Response.Status.BAD_REQUEST, \"Namespace does not exist\");\n                }\n            }\n        } catch (PulsarAdminException.NotAuthorizedException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .attr(\"componentType\", ComponentTypeUtils.toString(componentType))\n\n                    .log(\"/ / Client is not authorized to operate on tenant\");\n            throw new RestException(Response.Status.UNAUTHORIZED, \"Client is not authorized to perform operation\");\n        } catch (PulsarAdminException.NotFoundException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .attr(\"tenant3\", tenant).log(\"/ / Tenant does not exist\");\n            throw new RestException(Response.Status.BAD_REQUEST, \"Tenant does not exist\");\n        } catch (PulsarAdminException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .exception(e).log(\"/ / Issues getting tenant data\");\n            throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());\n        }\n\n        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();\n\n        if (functionMetaDataManager.containsFunction(tenant, namespace, functionName)) {\n            log.error().attr(\"componentType\", ComponentTypeUtils.toString(componentType)).attr(\"tenant\", tenant)\n\n                    .attr(\"namespace\", namespace).attr(\"componentName\", functionName).log(\"/ / already exists\");","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Grant the calling role tenant admin/functions permissions: 'pulsar-admin tenants update ... --admin-roles' or namespaces grant-permission","Verify the client credentials (token/Athenz/K8s secret) belong to an authorized role","Check the functions worker's brokerClientAuthenticationPlugin/Parameters are valid so worker-to-broker calls are authorized"],"exampleFix":"// before\n// role 'fn-user' has no permissions on tenant 'public'\n// after\npulsar-admin tenants update public --admin-roles fn-user\n# or\npulsar-admin namespaces grant-permission public/default --role fn-user --permissions functions","handlingStrategy":"try-catch","validationCode":"try {\n    admin.namespaces().getNamespaces(tenant); // probes authorization\n} catch (PulsarAdminException.NotAuthorizedException e) {\n    throw new IllegalStateException(\"role lacks permissions on \" + tenant, e);\n}","typeGuard":null,"tryCatchPattern":"try { admin.functions().createFunction(...); }\ncatch (PulsarAdminException.NotAuthorizedException e) {\n    // refresh credentials or grant admin/tenant role, then retry\n}","preventionTips":["Grant the deployment principal tenant admin-roles or functions permissions up front","Verify token expiry and role claims before running pipelines","Keep the functions worker's broker client auth configuration valid"],"tags":["authorization","pulsar-functions","security"],"backgroundTag":"unauthorized-client","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"}