{"record":{"id":"88a0befb1131180d","repo":"aeron-io/aeron","slug":"unexpected-driver-close","errorCode":null,"errorMessage":"unexpected driver close","messagePattern":"unexpected driver close","errorType":"exception","errorClass":"AgentTerminationException","httpStatus":null,"severity":"critical","filePath":"aeron-archive/src/main/java/io/aeron/archive/ArchiveConductor.java","lineNumber":436,"sourceCode":"                isAbort = true;\n                throw new AgentTerminationException(\"unexpected Aeron close\");\n            }\n        }\n\n        return workCount;\n    }\n\n    final int invokeDriverConductor()\n    {\n        int workCount = 0;\n\n        if (null != driverAgentInvoker)\n        {\n            workCount += driverAgentInvoker.invoke();\n\n            if (driverAgentInvoker.isClosed())\n            {\n                throw new AgentTerminationException(\"unexpected driver close\");\n            }\n        }\n\n        return workCount;\n    }\n\n    void logWarning(final String message)\n    {\n        errorHandler.onError(new ArchiveEvent(message));\n    }\n\n    ControlSession newControlSession(\n        final Image image,\n        final long correlationId,\n        final int streamId,\n        final int version,\n        final String channel,\n        final byte[] encodedCredentials,","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/ArchiveConductor.java#L418-L454","documentation":"invokeDriverConductor runs the media driver's AgentInvoker inside the archive conductor. If after invoking it the driver invoker reports closed (driverAgentInvoker.isClosed()), the conductor throws AgentTerminationException(\"unexpected driver close\"). The archive requires a live media driver and aborts when the driver goes away unexpectedly.","triggerScenarios":"Media driver is closed/crashes (driverAgentInvoker.isClosed() returns true) while ArchiveConductor.invokeDriverConductor() runs inside doWork().","commonSituations":"Embedded driver closed by another component first; driver process killed or exited (OOM, external kill); driver shut down via its own shutdown hook before the archive; use of a driver invoker bound to a closed driver context.","solutions":["Ensure the media driver outlives the archive: close the Archive first, then the driver.","Check driver logs for crash/OOM causing the driver agent to exit.","If running an embedded driver, manage ordering in a single owner component (e.g. try-with-resources with driver declared last).","If the driver is intentionally shut down, stop the Archive agent before closing the driver."],"exampleFix":"// before\ndriver.close();\narchive.close();\n\n// after\narchive.close();\ndriver.close();","handlingStrategy":"try-catch","validationCode":"// guard before duty cycle\nif (driverAgentInvoker != null && driverAgentInvoker.isClosed()) {\n    throw new AgentTerminationException(\"driver already closed\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    conductor.doWork();\n} catch (AgentTerminationException e) {\n    if (e.getMessage().contains(\"driver close\")) {\n        log.error(\"Media driver closed unexpectedly; stopping archive agent\", e);\n    }\n}","preventionTips":["Close archive before driver in shutdown paths.","Monitor driver process health (no OOM/kill).","If using an external driver, verify it is up before launching the archive.","Keep driver and archive lifecycles in one owner component."],"tags":["aeron-archive","media-driver","lifecycle","shutdown"],"backgroundTag":"invalid-state-transition","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}