{"record":{"id":"331891a80033fb8c","repo":"apache/pulsar","slug":"couldn-t-find-subscription","errorCode":null,"errorMessage":"couldn't find subscription","messagePattern":"couldn't find subscription","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java","lineNumber":467,"sourceCode":"                throw new IllegalStateException(\"policies are in readonly mode\");\n            }\n            return pulsarResources.getNamespaceResources()\n                    .setPoliciesAsync(namespace, policies -> {\n                        if (remove) {\n                            Set<String> subscriptionAuth =\n                                    policies.auth_policies.getSubscriptionAuthentication().get(subscriptionName);\n                            if (subscriptionAuth != null) {\n                                subscriptionAuth.removeAll(roles);\n                                if (subscriptionAuth.isEmpty()) {\n                                    policies.auth_policies.getSubscriptionAuthentication().remove(subscriptionName);\n                                }\n                            } else {\n                                log.info()\n                                        .attr(\"namespace\", namespace)\n                                        .attr(\"role\", roles)\n                                        .attr(\"sub\", subscriptionName)\n                                        .log(\"Couldn't find role while revoking for sub\");\n                                throw new IllegalArgumentException(\"couldn't find subscription\");\n                            }\n                        } else {\n                            policies.auth_policies.getSubscriptionAuthentication().put(subscriptionName, roles);\n                        }\n                        return policies;\n                    }).whenComplete((__, throwable) -> {\n                        if (throwable != null) {\n                            log.error()\n                                    .attr(\"subscriptionName\", subscriptionName)\n                                    .attr(\"role\", roles)\n                                    .attr(\"namespace\", namespace)\n                                    .exception(throwable)\n                                    .log(\"Failed to set permissions for role on namespace\");\n                        } else {\n                            log.info()\n                                    .attr(\"namespace\", namespace)\n                                    .attr(\"role\", roles)\n                                    .attr(\"sub\", subscriptionName)","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java#L449-L485","documentation":"When revoking subscription permissions, updateSubscriptionPermissionAsync removes the role set if it exists; if the subscription has no entry (or the roles set doesn't contain the role) in the policies, it throws IllegalArgumentException('couldn't find subscription'). This is a client/consistency error: the caller asked to revoke from a subscription that has no recorded permissions.","triggerScenarios":"revokeSubscriptionPermissionAsync on a subscription that was never granted permissions, was already fully revoked, or whose policies entry was removed concurrently.","commonSituations":"Double-revoke from retries or two admins; revoking against a renamed subscription; stale client view of existing subscription permissions; typo in subscription name.","solutions":["Check GET /namespaces/{ns}/permissions/subscription first and skip the revoke if the subscription/role is absent","Treat the failed future as idempotent success in the caller if the goal is 'role no longer has access'","Correct the subscription name and retry","Handle races by catching IllegalArgumentException from the revoke and continuing"],"exampleFix":"// before\nawait authorization.revokeSubscriptionPermissionAsync(ns, sub, role);\n// after\nMap<String, Set<String>> subs =\n    await authorization.getSubscriptionPermissionsAsync(ns);\nif (subs.containsKey(sub) && subs.get(sub).contains(role)) {\n    await authorization.revokeSubscriptionPermissionAsync(ns, sub, role);\n}","handlingStrategy":"validation","validationCode":"Map<String, Set<String>> subPerms =\n    authorization.getSubscriptionPermissionsAsync(namespace).get();\nif (!subPerms.containsKey(subscriptionName)\n        || !subPerms.get(subscriptionName).contains(role)) {\n    return; // nothing to revoke\n}","typeGuard":null,"tryCatchPattern":"try {\n    revokeSubFuture.get();\n} catch (ExecutionException e) {\n    if (e.getCause() instanceof IllegalArgumentException) {\n        // treat as idempotent no-op\n    }\n}","preventionTips":["Read current subscription permissions before revoking","Make revoke operations idempotent in callers","Validate subscription names against the namespace's policies","Guard against double-revokes from client retries"],"tags":["pulsar","authorization","subscription","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}