{"record":{"id":"ce0b3a31f54579c5","repo":"apache/pulsar","slug":"don-t-have-permission-to-connect-to-this-namespace","errorCode":null,"errorMessage":"Don't have permission to connect to this namespace","messagePattern":"Don't have permission to connect to this namespace","errorType":"http","errorClass":"RestException","httpStatus":401,"severity":"warning","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java","lineNumber":961,"sourceCode":"    }\n\n    protected static CompletableFuture<Void> checkAuthorizationAsync(PulsarService pulsarService, TopicName topicName,\n                        String role, String originalPrinciple, AuthenticationDataSource authenticationData,\n                        AuthenticationDataSource originalAuthenticationData) {\n        if (!pulsarService.getConfiguration().isAuthorizationEnabled()) {\n            // No enforcing of authorization policies\n            return CompletableFuture.completedFuture(null);\n        }\n        // get zk policy manager\n        return pulsarService.getBrokerService().getAuthorizationService().allowTopicOperationAsync(topicName,\n                TopicOperation.LOOKUP, originalPrinciple, role, originalAuthenticationData, authenticationData)\n                .thenAccept(allow -> {\n                    if (!allow) {\n                        LOG.warn()\n                                .attr(\"topic\", topicName)\n                                .attr(\"role\", role)\n                                .log(\"Role is not allowed to lookup topic\");\n                        throw new RestException(Status.UNAUTHORIZED,\n                                \"Don't have permission to connect to this namespace\");\n                    }\n        });\n    }\n\n    // Used for unit tests access\n    public void setPulsar(PulsarService pulsar) {\n        this.pulsar = pulsar;\n    }\n\n    protected boolean isLeaderBroker() {\n        return isLeaderBroker(pulsar());\n    }\n\n    protected static boolean isLeaderBroker(PulsarService pulsar) {\n        // For extensible load manager, it doesn't have leader election service on pulsar broker.\n        if (ExtensibleLoadManagerImpl.isLoadManagerExtensionEnabled(pulsar)) {\n            return true;","sourceCodeStart":943,"sourceCodeEnd":979,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java#L943-L979","documentation":"HTTP 401 UNAUTHORIZED thrown by canLookupTopic (validateTopicOperation-style path): the authorization service decided the given role is not allowed to look up (connect to) the topic's namespace. The client cannot discover or attach to the topic.","triggerScenarios":"A client calls topic lookup (or an admin operation that performs lookup) with a role lacking 'consume'/'lookup' authorization on the namespace; superuser checks fail and namespace-level authorization denies the role.","commonSituations":"Missing grant for the client's role on the namespace; role changed after rotating credentials (e.g. new OIDC subject); authorizationEnabled=true but policies never granted the role; wildcard role patterns not matching the actual role.","solutions":["Grant the role lookup/produce/consume permission: admin.namespaces().grantPermissionOnNamespace(ns, role, Set.of(AuthAction.consume))","Verify the client is authenticating with the role you intend (check clientAppId/originalPrincipal in broker logs)","If using wildcard role matching, ensure the policy pattern actually matches the authenticated role","If the principal differs from the authenticated one (proxy scenarios), also grant the originalPrincipal"],"exampleFix":"// before: role denied at lookup\nPulsarAdmin admin = PulsarAdmin.builder().serviceHttpUrl(...).authentication(...).build();\n// after (as superuser) grant the action\nadmin.namespaces().grantPermissionOnNamespace(\"public/default\", \"my-role\",\n    Set.of(NamespaceOperation.PRODUCE, NamespaceOperation.CONSUME));","handlingStrategy":"try-catch","validationCode":"try {\n    Map<String, Set<AuthAction>> perms = admin.namespaces().getPermissions(ns);\n    if (!perms.containsKey(myRole)) throw new IllegalStateException(\"role has no grants on namespace\");\n} catch (PulsarAdminException e) { /* not authorized even to read */ }","typeGuard":null,"tryCatchPattern":"try {\n    lookupTopic(topic);\n} catch (PulsarAdminException e) {\n    if (e.getStatusCode() == 401 && e.getMessage().contains(\"permission to connect\")) {\n        throw new SecurityException(\"grant consume/lookup on namespace to role first\", e);\n    } else throw e;\n}","preventionTips":["Grant namespace permissions before deploying clients","Confirm the authenticated role name matches grants after credential rotation","Use getPermissions to verify grants pre-launch"],"tags":["http-401","authorization","permissions","topic-lookup"],"backgroundTag":"missing-permission-grant","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"}