{"record":{"id":"b2a85c84ecc6f112","repo":"apache/druid","slug":"cannot-start-once-already-started-or-closed","errorCode":null,"errorMessage":"Cannot start once already started or closed","messagePattern":"Cannot start once already started or closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/rpc/DiscoveryServiceLocator.java","lineNumber":96,"sourceCode":"        return Futures.immediateFuture(ServiceLocations.closed());\n      } else if (initialized) {\n        return Futures.immediateFuture(ServiceLocations.forLocations(ImmutableSet.copyOf(locations)));\n      } else {\n        if (pendingFuture == null) {\n          pendingFuture = SettableFuture.create();\n        }\n\n        return Futures.nonCancellationPropagating(pendingFuture);\n      }\n    }\n  }\n\n  @LifecycleStart\n  public void start()\n  {\n    synchronized (this) {\n      if (started || closed) {\n        throw new ISE(\"Cannot start once already started or closed\");\n      } else {\n        started = true;\n        this.discovery = discoveryProvider.getForNodeRole(nodeRole);\n        discovery.registerListener(listener);\n      }\n    }\n  }\n\n  @Override\n  @LifecycleStop\n  public void close()\n  {\n    synchronized (this) {\n      // Idempotent: can call close() multiple times so long as start() has already been called.\n      if (started && !closed) {\n        if (discovery != null) {\n          discovery.removeListener(listener);\n        }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/rpc/DiscoveryServiceLocator.java#L78-L114","documentation":"DiscoveryServiceLocator.start() is annotated @LifecycleStart and may only be called once, and only while not closed. If the service locator has already been started or has been closed, calling start() again throws an IllegalStateException.","triggerScenarios":"Calling start() twice on the same DiscoveryServiceLocator, or calling start() after close() has been invoked; double lifecycle registration (e.g., adding the same object to a Guava Lifecycle twice).","commonSituations":"Misconfigured DI wiring where the locator is both lifecycle-managed and manually started; test code restarting a locator without recreating it; lifecycle restart attempts after shutdown.","solutions":["Call start() exactly once per instance; create a new instance if you need to start again.","Do not call start() after close(); replace the closed instance instead.","Remove duplicate lifecycle.addAndGetRegisteredObject/start calls for this bean.","Check wiring (e.g., Jersey/Guice modules) so the locator is managed by a single lifecycle."],"exampleFix":"// before\nlocator.start();\nlocator.close();\nlocator.start(); // throws\n// after\nlocator.start();\nlocator.close();\nlocator = new DiscoveryServiceLocator(discoveryProvider, nodeRole, listener);\nlocator.start();","handlingStrategy":"type-guard","validationCode":"// Java: guard before starting\n// assume 'started'/'closed' exposed or tracked by caller\nif (!locatorStarted && !locatorClosed) { locator.start(); locatorStarted = true; }","typeGuard":"boolean canStart(DiscoveryServiceLocator l, boolean startedFlag, boolean closedFlag) { return !startedFlag && !closedFlag; }","tryCatchPattern":"try { locator.start(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Cannot start once already started\")) { /* already running or closed: treat as no-op or recreate */ } else { throw e; } }","preventionTips":["Manage lifecycle via a single Guava Lifecycle registration","Never restart a closed instance; construct a new one","Avoid mixing manual start() calls with lifecycle-managed start","Track start/close state in wrapping code"],"tags":["lifecycle","service-discovery","invalid-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-14T05:17:10.506Z"}