{"record":{"id":"47a3dcf8db362472","repo":"apache/pulsar","slug":"subscription-has-active-connected-consumers","errorCode":null,"errorMessage":"Subscription has active connected consumers","messagePattern":"Subscription has active connected consumers","errorType":"http","errorClass":"RestException","httpStatus":412,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java","lineNumber":2372,"sourceCode":"                                    if (optTopic.isEmpty()) {\n                                        return CompletableFuture.completedFuture(null);\n                                    }\n                                    Topic loaded = optTopic.get();\n                                    Subscription sub = loaded.getSubscription(subscription);\n                                    if (sub == null) {\n                                        return CompletableFuture.completedFuture(null);\n                                    }\n                                    return sub.delete();\n                                }));\n                    }\n                    return FutureUtil.waitForAll(futures);\n                }).exceptionally(ex -> {\n                    Throwable cause = FutureUtil.unwrapCompletionException(ex);\n                    if (cause instanceof RestException) {\n                        throw (RestException) cause;\n                    }\n                    if (cause instanceof SubscriptionBusyException) {\n                        throw new RestException(Status.PRECONDITION_FAILED,\n                                \"Subscription has active connected consumers\");\n                    }\n                    throw new RestException(cause);\n                });\n    }\n\n    protected BundlesData validateBundlesData(BundlesData initialBundles) {\n        SortedSet<String> partitions = new TreeSet<String>();\n        for (String partition : initialBundles.getBoundaries()) {\n            Long partBoundary = Long.decode(partition);\n            partitions.add(String.format(\"0x%08x\", partBoundary));\n        }\n        if (partitions.size() != initialBundles.getBoundaries().size()) {\n                log.debug(\"Input bundles included repeated partition points. Ignored.\");\n                    }\n        try {\n            NamespaceBundleFactory.validateFullRange(partitions);\n        } catch (IllegalArgumentException iae) {","sourceCodeStart":2354,"sourceCodeEnd":2390,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java#L2354-L2390","documentation":"Thrown when deleting a subscription from a namespace via the admin API: the broker attempted the deletion but a SubscriptionBusyException occurred because consumers are still actively connected to that subscription. It is translated to HTTP 412 PRECONDITION_FAILED, telling the caller the subscription cannot be removed while in use.","triggerScenarios":"DELETE /namespaces/{ns}/subscription/{sub} (or namespace-level unsubscribe of a persistent subscription) while live consumers with that subscription name are connected; failing to close/drain all readers/consumers (including shared/exclusive consumers in other clients) before deletion.","commonSituations":"CI teardown scripts that don't close consumers before cleaning namespaces; streaming apps with redundant consumer instances still running; lingering readers (cursor-based) attached to the subscription; force flag omitted while consumers are active.","solutions":["Close all consumers/readers using the subscription, then retry the deletion","Pass force=true to the delete call to disconnect consumers and force-delete (use with care: in-flight messages may be lost)","Identify connected consumers via GET /persistent/{tenant}/{ns}/{topic}/subscriptions/{sub}/... stats and shut them down","Wait for consumer clients to reconnect/disconnect (e.g. after a rolling restart) before retrying"],"exampleFix":"// before\nadmin.namespaces().deleteSubscription(\"my-tenant/my-ns\", \"my-sub\"); // 412 if consumers connected\n// after\nconsumer.close(); // close all consumers of 'my-sub' first\nadmin.namespaces().deleteSubscription(\"my-tenant/my-ns\", \"my-sub\");\n// or force:\nadmin.namespaces().deleteSubscription(\"my-tenant/my-ns\", \"my-sub\", true);","handlingStrategy":"try-catch","validationCode":"PersistentTopicInternalStats stats = null;\n// prefer checking consumers before delete:\n// if any consumer entries exist under the subscription, close them first\nboolean hasConsumers = topicStats != null && topicStats.subscriptions\n    .getOrDefault(sub, new SubscriptionStats()).consumers.size() > 0;\nif (hasConsumers) throw new IllegalStateException(\"Close consumers of \" + sub + \" before deletion\");","typeGuard":null,"tryCatchPattern":"try {\n    admin.namespaces().deleteSubscription(ns, sub);\n} catch (PulsarAdminException.PreconditionFailedException e) {\n    // consumers still connected: either close them or force-delete\n    admin.namespaces().deleteSubscription(ns, sub, true);\n}","preventionTips":["Close all client consumers/readers in teardown scripts before deleting subscriptions","Use force=true only after confirming in-flight data loss is acceptable","Check subscription consumer stats before deletion"],"tags":["http-412","subscription","consumers","admin-api"],"backgroundTag":"subscription-busy-consumers-connected","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"}