{"record":{"id":"b0c22e72e18d2766","repo":"apache/druid","slug":"emit-called-unexpectedly-before-service-start-b0c22e","errorCode":null,"errorMessage":"Emit called unexpectedly before service start","messagePattern":"Emit called unexpectedly before service start","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/opentsdb-emitter/src/main/java/org/apache/druid/emitter/opentsdb/OpentsdbEmitter.java","lineNumber":69,"sourceCode":"  }\n\n  @Override\n  public void start()\n  {\n    synchronized (started) {\n      if (!started.get()) {\n        log.info(\"Starting Opentsdb Emitter.\");\n        sender.start();\n        started.set(true);\n      }\n    }\n  }\n\n  @Override\n  public void emit(Event event)\n  {\n    if (!started.get()) {\n      throw new ISE(\"Emit called unexpectedly before service start\");\n    }\n    if (event instanceof ServiceMetricEvent) {\n      OpentsdbEvent opentsdbEvent = converter.convert((ServiceMetricEvent) event);\n      if (opentsdbEvent != null) {\n        sender.enqueue(opentsdbEvent);\n      } else {\n        log.debug(\n            \"Metric=[%s] has not been configured to be emitted to opentsdb\",\n            ((ServiceMetricEvent) event).getMetric()\n        );\n      }\n    }\n  }\n\n  @Override\n  public void flush()\n  {\n    if (started.get()) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/opentsdb-emitter/src/main/java/org/apache/druid/emitter/opentsdb/OpentsdbEmitter.java#L51-L87","documentation":"OpentsdbEmitter.emit checks an internal 'started' flag before processing events; emitting before start() was called means the sender and converter are not yet initialized, so it fails fast with ISE rather than silently dropping metrics.","triggerScenarios":"Calling emitter.emit(event) before emitter.start(), e.g. a custom emitter pipeline registering the OpentsdbEmitter but not invoking start(), or emitting from another thread racing with service startup.","commonSituations":"Wiring the emitter into Druid's emitter list manually without lifecycle start, unit tests invoking emit directly, or ordering bugs where metrics are emitted during module initialization.","solutions":["Ensure emitter.start() is called before any emit() (normally Druid's Emitters service lifecycle does this)","If wiring manually, register the emitter with the lifecycle or call start() explicitly after construction","Guard early metric emissions so they occur only after service start, or flush/buffer events until started"],"exampleFix":"// before\nemitter.emit(event); // may run before start\n// after\nif (emitter.isStarted()) {\n  emitter.emit(event);\n}","handlingStrategy":"try-catch","validationCode":"if (!emitter.isStarted()) { throw new IllegalStateException(\"start the emitter before emitting events\"); }","typeGuard":null,"tryCatchPattern":"try { emitter.emit(event); } catch (IllegalStateException e) { if (e.getMessage().contains(\"before service start\")) { emitter.start(); emitter.emit(event); } }","preventionTips":["Rely on Druid's lifecycle to start emitters; don't bypass Emitters.create","In tests, call start() in @BeforeEach and close() in @AfterEach","Avoid emitting metrics during module static initialization"],"tags":["java","lifecycle","emitter","opentsdb"],"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"}