apache/druid · error · IllegalStateException
Emit called unexpectedly before service start
Error message
Emit called unexpectedly before service start
What it means
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.
Source
Thrown at extensions-contrib/opentsdb-emitter/src/main/java/org/apache/druid/emitter/opentsdb/OpentsdbEmitter.java:69
}
@Override
public void start()
{
synchronized (started) {
if (!started.get()) {
log.info("Starting Opentsdb Emitter.");
sender.start();
started.set(true);
}
}
}
@Override
public void emit(Event event)
{
if (!started.get()) {
throw new ISE("Emit called unexpectedly before service start");
}
if (event instanceof ServiceMetricEvent) {
OpentsdbEvent opentsdbEvent = converter.convert((ServiceMetricEvent) event);
if (opentsdbEvent != null) {
sender.enqueue(opentsdbEvent);
} else {
log.debug(
"Metric=[%s] has not been configured to be emitted to opentsdb",
((ServiceMetricEvent) event).getMetric()
);
}
}
}
@Override
public void flush()
{
if (started.get()) {View on GitHub (pinned to 9b90983fd2)
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
Example fix
// before
emitter.emit(event); // may run before start
// after
if (emitter.isStarted()) {
emitter.emit(event);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!emitter.isStarted()) { throw new IllegalStateException("start the emitter before emitting events"); } Try / catch
try { emitter.emit(event); } catch (IllegalStateException e) { if (e.getMessage().contains("before service start")) { emitter.start(); emitter.emit(event); } } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Failed to parse metrics and dimensions
- Failed to parse metric configuration
- Service is closed.
- Already started
- can't stop.
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b0c22e72e18d2766.
Report an issue: GitHub.