{"record":{"id":"f8046053fe087d03","repo":"apache/druid","slug":"service-not-started","errorCode":null,"errorMessage":"Service not started.","messagePattern":"Service not started\\.","errorType":"error_code","errorClass":"RejectedExecutionException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/java/util/emitter/core/LoggingEmitter.java","lineNumber":187,"sourceCode":"            log.info(message, started.get());\n          }\n          break;\n        case WARN:\n          log.warn(message, started.get());\n          break;\n        case ERROR:\n          log.error(message, started.get());\n          break;\n      }\n    }\n  }\n\n  @Override\n  public void emit(Event event)\n  {\n    synchronized (started) {\n      if (!started.get()) {\n        throw new RejectedExecutionException(\"Service not started.\");\n      }\n    }\n\n    // Allowlist filtering: only applies to ServiceMetricEvents.\n    // Non-metric events (alerts, etc.) always pass through.\n    if (allowedMetrics != null && event instanceof ServiceMetricEvent) {\n      final String metricName = ((ServiceMetricEvent) event).getMetric();\n      if (!allowedMetrics.contains(metricName)) {\n        return;\n      }\n    }\n\n    try {\n      switch (level) {\n        case TRACE:\n          if (log.isTraceEnabled()) {\n            log.trace(MarkerFactory.getMarker(event.getFeed()), jsonMapper.writeValueAsString(event));\n          }","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/emitter/core/LoggingEmitter.java#L169-L205","documentation":"LoggingEmitter writes events to a log, but only after start() has been called; emit() synchronizes on the started AtomicBoolean and throws RejectedExecutionException('Service not started.') if emit is invoked before start(). Unlike HttpPostEmitter, it checks only started state at call time.","triggerScenarios":"Calling emit(Event) on a LoggingEmitter whose start() was never invoked; emitting after close() reset the flag; constructing the emitter manually in tests or embedded code without calling start().","commonSituations":"Unit tests constructing LoggingEmitter without lifecycle start; wiring emitters into a custom ServiceMetrics config before Lifecycle start; using an emitter obtained from a stopped injector/Lifecycle.","solutions":["Call emitter.start() before any emit, typically via Druid Lifecycle initialization.","In tests, invoke start() in setup or use the Lifecycle to manage the emitter.","Catch RejectedExecutionException around emit if emission may occur before start.","Ensure close()/stop() is only called after all producers have finished."],"exampleFix":"// before\nLoggingEmitter emitter = new LoggingEmitter(config, mapper);\nemitter.emit(event); // RejectedExecutionException\n// after\nLoggingEmitter emitter = new LoggingEmitter(config, mapper);\nemitter.start();\nemitter.emit(event);","handlingStrategy":"try-catch","validationCode":"// AtomicBoolean started is private; track your own start state\nif (!emitterStarted) { startEmitterOrSkip(event); return; }","typeGuard":null,"tryCatchPattern":"try {\n  emitter.emit(event);\n} catch (RejectedExecutionException e) {\n  log.debug(e, \"LoggingEmitter not started; dropping event\");\n}","preventionTips":["Always call start() before emitting","Manage emitters via Druid Lifecycle rather than manual construction","In tests, start the emitter in @BeforeEach"],"tags":["lifecycle","logging-emitter","rejected-execution"],"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-14T11:17:12.474Z"}