{"record":{"id":"21cdb978b8de6ccc","repo":"apache/druid","slug":"listener-s-already-registered","errorCode":null,"errorMessage":"Listener [%s] already registered","messagePattern":"Listener \\[(.+?)\\] already registered","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunner.java","lineNumber":535,"sourceCode":"\n  @Override\n  public void unregisterListener(String listenerId)\n  {\n    for (Pair<TaskRunnerListener, Executor> pair : listeners) {\n      if (pair.lhs != null && pair.lhs.getListenerId().equals(listenerId)) {\n        listeners.remove(pair);\n        log.debug(\"Unregistered listener [%s]\", listenerId);\n        return;\n      }\n    }\n  }\n\n  @Override\n  public void registerListener(TaskRunnerListener listener, Executor executor)\n  {\n    for (Pair<TaskRunnerListener, Executor> pair : listeners) {\n      if (pair.lhs != null && pair.lhs.getListenerId().equals(listener.getListenerId())) {\n        throw new ISE(\"Listener [%s] already registered\", listener.getListenerId());\n      }\n    }\n\n    final Pair<TaskRunnerListener, Executor> listenerPair = Pair.of(listener, executor);\n    log.debug(\"Registered listener [%s]\", listener.getListenerId());\n    listeners.add(listenerPair);\n  }\n\n  @Override\n  public Collection<TaskRunnerWorkItem> getRunningTasks()\n  {\n    return tasks.values()\n                .stream()\n                .filter(KubernetesWorkItem::isRunning)\n                .collect(Collectors.toList());\n  }\n\n  @Override","sourceCodeStart":517,"sourceCodeEnd":553,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunner.java#L517-L553","documentation":"KubernetesTaskRunner.registerListener() throws this IllegalStateException when a listener with the same listenerId is already registered. The runner keeps a list of (listener, executor) pairs and enforces unique listener IDs so status-change notifications are delivered exactly once per subscriber.","triggerScenarios":"Registering the same TaskRunnerListener instance (or two listeners with equal getListenerId()) twice; re-registering after a restart of the calling component without unregistering first; multiple Overlord subsystems sharing one listenerId string.","commonSituations":"TaskMaster/re-subscription logic re-adding a listener on reconnect; tests registering a listener in setup for every case on a shared runner; two services both passing 'overlord' as listenerId.","solutions":["Use a unique listenerId per registration, or reuse the same one intentionally and skip re-registration","Unregister (removeListener) before registering again with the same ID","Check the listeners list (or track locally) before calling registerListener","In tests, use a fresh runner or distinct IDs per test case"],"exampleFix":"// before\nrunner.registerListener(listener, executor);\n// re-subscribe path\nrunner.registerListener(listener, executor); // ISE\n// after\nrunner.removeListener(listener);\nrunner.registerListener(listener, executor);","handlingStrategy":"try-catch","validationCode":"boolean alreadyRegistered = registeredIds.contains(listener.getListenerId());\nif (!alreadyRegistered) { taskRunner.registerListener(listener, executor); }","typeGuard":null,"tryCatchPattern":"try {\n  taskRunner.registerListener(listener, executor);\n} catch (IllegalStateException e) {\n  // listener already registered; skip or re-register after removeListener\n}","preventionTips":["Use a unique listenerId per subscriber","Call removeListener before re-registering","Avoid sharing listenerId strings across services/tests"],"tags":["kubernetes","task-runner","duplicate-listener","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}