{"record":{"id":"966bd051b9f0a134","repo":"aeron-io/aeron","slug":"unexpected-interrupt","errorCode":null,"errorMessage":"unexpected interrupt","messagePattern":"unexpected interrupt","errorType":"exception","errorClass":"AeronException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java","lineNumber":2357,"sourceCode":"        }\n        finally\n        {\n            lock.unlock();\n        }\n    }\n\n    private void checkDeadline(final long deadlineNs, final String errorMessage, final long correlationId)\n    {\n        if (deadlineNs - nanoClock.nanoTime() < 0)\n        {\n            throw new TimeoutException(\n                errorMessage + \" - correlationId=\" + correlationId + \" messageTimeout=\" +\n                SystemUtil.formatDuration(messageTimeoutNs));\n        }\n\n        if (Thread.currentThread().isInterrupted())\n        {\n            throw new AeronException(\"unexpected interrupt\");\n        }\n    }\n\n    private void pollNextResponse(final long correlationId, final long deadlineNs, final ControlResponsePoller poller)\n    {\n        idleStrategy.reset();\n\n        while (true)\n        {\n            final int fragments = poller.poll();\n\n            if (poller.isPollComplete())\n            {\n                if (poller.templateId() == RecordingSignalEventDecoder.TEMPLATE_ID &&\n                    poller.controlSessionId() == controlSessionId)\n                {\n                    dispatchRecordingSignal(poller);\n                    continue;","sourceCodeStart":2339,"sourceCodeEnd":2375,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java#L2339-L2375","documentation":"AeronException thrown by checkDeadline when the calling thread's interrupt flag is set while awaiting an archive response. Aeron's lock-free structures and idle strategies are not interrupt-safe for this flow, so the client aborts the wait instead of silently spinning on an interrupted thread.","triggerScenarios":"Another thread calls Thread.interrupt() (or an executor shutdownNow()) on the thread blocked in pollForResponse/pollNextResponse waiting for the archive response.","commonSituations":"Cancelling a long archive request via executor shutdownNow; test frameworks interrupting leaked threads; application shutdown logic interrupting archive-client worker threads; accidental shared-thread interruption when Aeron is embedded in a container that interrupts its threads.","solutions":["Remove or scope down code that interrupts the archive client thread; use cancellation flags instead.","Run archive client calls on a dedicated thread not subject to shutdownNow() interruptions.","If interruption is intentional, catch AeronException, clear the flag semantics, and re-issue the request on a fresh thread.","Configure AeronArchive.Context.aeron()/idleStrategy so client polling runs on a thread you control."],"exampleFix":"// before\nexecutor.shutdownNow(); // interrupts in-flight archive call\n// after\narchiveCallThread.interrupt() avoided;\nvolatile boolean cancelled = true; // let the call finish and check flag","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    archive.startReplay(recordingId, pos, len, ch, streamId);\n} catch (AeronException e) {\n    if (\"unexpected interrupt\".equals(e.getMessage())) {\n        Thread.interrupted(); // clear flag; decide retry policy\n    }\n}","preventionTips":["Never call shutdownNow() on threads executing archive client calls.","Use cooperative cancellation flags instead of interrupts.","Dedicate a thread pool to archive client operations and document its no-interrupt contract."],"tags":["aeron-archive","threading","interrupt"],"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"}