{"record":{"id":"5d2b4d9048435924","repo":"apache/druid","slug":"failed-to-close-one-or-more-emitters-5d2b4d","errorCode":null,"errorMessage":"failed to close one or more emitters","messagePattern":"failed to close one or more emitters","errorType":"error_code","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/java/util/emitter/core/SwitchingEmitter.java","lineNumber":164,"sourceCode":"  @LifecycleStop\n  public void close() throws IOException\n  {\n    boolean fail = false;\n    log.info(\"Closing Switching Emitter.\");\n\n    for (Emitter e : knownEmitters) {\n      try {\n        log.info(\"Closing emitter %s.\", e.getClass().getName());\n        e.close();\n      }\n      catch (IOException ex) {\n        log.error(ex, \"Failed to close emitter [%s]\", e.getClass().getName());\n        fail = true;\n      }\n    }\n\n    if (fail) {\n      throw new IOException(\"failed to close one or more emitters\");\n    }\n  }\n}\n","sourceCodeStart":146,"sourceCodeEnd":168,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/emitter/core/SwitchingEmitter.java#L146-L168","documentation":"SwitchingEmitter routes events to one of several underlying emitters (alert, feed, etc.). During close(), it closes each child emitter; if any child throws an IOException, it remembers the failure and throws this aggregate IOException once all children have been attempted. It signals that at least one child emitter could not shut down cleanly, so buffered events may not have been flushed.","triggerScenarios":"Calling SwitchingEmitter.close() when any wrapped emitter's close() throws IOException — typically a UriEmitter/HttpEmitter whose flush to its HTTP endpoint fails, or an emitter whose writer is already closed or errored.","commonSituations":"Druid service shutdown while the HTTP emitter's target (e.g. a metrics/alerting endpoint) is down or slow; double-close of emitters; disk or network issues preventing the child emitter from flushing its queue during close.","solutions":["Check the accompanying 'Failed to close emitter [<class>]' log lines to identify which child emitter(s) failed and fix the root cause (network, endpoint availability).","Ensure the child emitters' target endpoints are reachable and draining correctly before/while shutting down the service.","Verify close() is only called once per emitter lifecycle; avoid closing an already-closed emitter.","If the failure is during process shutdown and data loss is acceptable for those metrics, this can often be logged and ignored.","Flush or wait for the emitter's internal queue to drain (e.g. call flush() and wait) before close() to reduce failure risk."],"exampleFix":"// before\nswitchingEmitter.close(); // may throw IOException, swallowing other pending shutdown work\n// after\ntry {\n  emitter.flush();\n  switchingEmitter.close();\n} catch (IOException e) {\n  log.warn(e, \"Some emitters failed to close during shutdown; continuing\");\n}","handlingStrategy":"try-catch","validationCode":"// before close, ensure children can flush\nswitchingEmitter.flush();","typeGuard":null,"tryCatchPattern":"try {\n  switchingEmitter.close();\n} catch (IOException e) {\n  log.warn(e, \"Emitter close failed on shutdown; some events may not have been flushed\");\n}","preventionTips":["Register emitters in the Druid lifecycle so close happens once, in order, at shutdown","Keep emitter endpoints healthy; monitor the target service availability","Call flush() and let queues drain before close()","Never close the same emitter twice"],"tags":["shutdown","emitter","io","resource-cleanup"],"backgroundTag":"file-write-failed","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"}