{"record":{"id":"5197a0165c7d8e78","repo":"aeron-io/aeron","slug":"interrupted-clusteredserviceagent","errorCode":null,"errorMessage":"interrupted","messagePattern":"interrupted","errorType":"exception","errorClass":"AgentTerminationException","httpStatus":null,"severity":"critical","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceAgent.java","lineNumber":436,"sourceCode":"    {\n        idleStrategy.idle();\n        doIdleWork();\n    }\n\n    public void idle(final int workCount)\n    {\n        idleStrategy.idle(workCount);\n        if (workCount <= 0)\n        {\n            doIdleWork();\n        }\n    }\n\n    private void doIdleWork()\n    {\n        if (Thread.currentThread().isInterrupted())\n        {\n            throw new AgentTerminationException(\"interrupted\");\n        }\n\n        final long nowNs = nanoClock.nanoTime();\n\n        checkForClockTick(nowNs);\n\n        if (isServiceActive)\n        {\n            invokeBackgroundWork(nowNs);\n        }\n    }\n\n    void onJoinLog(\n        final long logPosition,\n        final long maxLogPosition,\n        final int memberId,\n        final int logSessionId,\n        final int logStreamId,","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceAgent.java#L418-L454","documentation":"ClusteredServiceAgent.doIdleWork checks Thread.currentThread().isInterrupted() and throws AgentTerminationException(\"interrupted\") if the duty-cycle thread has been interrupted. This is the agent's cooperative shutdown hook: interruption means the JVM or owner wants the cluster agent to stop, so it terminates the agent rather than continuing to idle.","triggerScenarios":"Another thread calls interrupt() on the cluster agent's duty-cycle thread — typically during shutdown, Thread.interrupt from a supervisor, or an ExecutorService.shutdownNow().","commonSituations":"Application shutdown hooks interrupting the cluster thread; container/executor shutdownNow(); misuse of interrupt() to signal work cancellation while a cluster agent is running on that thread.","solutions":["If shutdown is intended, let the agent terminate: use ClusteredServiceContainer/Cluster's proper close/stop methods instead of raw interrupt.","Do not run other interrupt-sensitive work on the cluster duty-cycle thread or interrupt it incidentally (e.g. from a shared ExecutorService.shutdownNow).","If interruption was accidental, restart the cluster container; the exception is intentionally terminal."],"exampleFix":"// before\nexecutor.shutdownNow(); // interrupts the cluster agent thread\n// after\ncluster.close(); // graceful stop, then\nexecutor.shutdown();","handlingStrategy":"try-catch","validationCode":"// java: before interrupting a thread hosting a cluster agent\nif (thread.getName().contains(\"cluster\") || agentThread == thread) {\n    throw new IllegalStateException(\"use the container's close()/stop(), not interrupt()\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    clusterContainer.start();\n} catch (AgentTerminationException e) {\n    // thread was interrupted during shutdown; treat as a deliberate stop and re-run\n    // clean up and restart only if the interruption was accidental\n}","preventionTips":["Stop cluster agents with their dedicated close()/stop() APIs, never Thread.interrupt().","Do not run the agent on threads managed by executors that call shutdownNow().","Ensure shutdown hooks close the cluster container gracefully before the JVM tears down."],"tags":["java","threading","interruption","shutdown"],"backgroundTag":"thread-interrupted","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}