{"record":{"id":"84864d5d4698c4ff","repo":"apache/druid","slug":"serviceid-s-already-announced-skipping","errorCode":null,"errorMessage":"ServiceId [%s] already announced, skipping","messagePattern":"ServiceId \\[(.+?)\\] already announced, skipping","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDruidNodeAnnouncer.java","lineNumber":159,"sourceCode":"  @Override\n  public void announce(DiscoveryDruidNode discoveryDruidNode)\n  {\n    if (!lifecycleLock.awaitStarted(1, TimeUnit.SECONDS)) {\n      throw new ISE(\"Announcer not started\");\n    }\n\n    String serviceId = ConsulServiceIds.serviceId(config, discoveryDruidNode);\n\n    // Prevent concurrent duplicate registrations for the same serviceId\n    if (!registeringNodes.add(serviceId)) {\n      LOGGER.warn(\"Registration already in progress for serviceId [%s]\", serviceId);\n      return;\n    }\n\n    try {\n      // If already announced, skip duplicate registration\n      if (announcedNodes.containsKey(serviceId)) {\n        LOGGER.warn(\"ServiceId [%s] already announced, skipping\", serviceId);\n        return;\n      }\n\n      long registerStart = System.nanoTime();\n\n      // Register in Consul, then track locally atomically in this block\n      registerServiceWithRetry(serviceId, discoveryDruidNode);\n      announcedNodes.put(serviceId, discoveryDruidNode);\n\n      long registerLatency = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - registerStart);\n      ConsulMetrics.emitTimer(emitter, \"consul/register/latency\", registerLatency,\n          \"role\", discoveryDruidNode.getNodeRole().getJsonName());\n\n      LOGGER.info(\"Successfully announced serviceId [%s]\", serviceId);\n      ConsulMetrics.emitCount(\n          emitter,\n          \"consul/announce/success\",\n          \"role\",","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDruidNodeAnnouncer.java#L141-L177","documentation":"Emitted in ConsulDruidNodeAnnouncer.announce when the serviceId is already present in announcedNodes, meaning the node was previously registered with Consul. The call is a no-op and skipped to avoid redundant or duplicate service registration.","triggerScenarios":"Calling announce() for a node whose serviceId is already registered and tracked — e.g. re-invoking announce after lifecycle restart, or a redundant announce from a second code path.","commonSituations":"Restarting the announcer lifecycle without stop() having deregistered; scripts/leadership logic re-announcing unchanged nodes.","solutions":["No action required — this is expected idempotent behavior; the service remains registered.","If you intended to refresh registration, call unannounce() first, then announce() again.","If seen unexpectedly, audit which component calls announce twice and remove the redundant call."],"exampleFix":"// before\nannouncer.announce(node); // called again after re-election\n// after\nif (!isAnnounced(node)) { announcer.announce(node); } // or rely on the built-in skip","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  announcer.announce(node);\n} catch (RuntimeException e) {\n  // skip if serviceId already announced\n}","preventionTips":["Track announced serviceIds in application code before calling announce","Call unannounce() before a deliberate re-announce","Rely on the built-in idempotent skip rather than duplicating calls"],"tags":["consul","registration","idempotency","duplicate"],"backgroundTag":"duplicate-registration-attempt","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"}