aeron-io/aeron · error · AeronException

unexpected interrupt

Error message

unexpected interrupt

What it means

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.

Solutions

  1. Remove or scope down code that interrupts the archive client thread; use cancellation flags instead.
  2. Run archive client calls on a dedicated thread not subject to shutdownNow() interruptions.
  3. If interruption is intentional, catch AeronException, clear the flag semantics, and re-issue the request on a fresh thread.
  4. Configure AeronArchive.Context.aeron()/idleStrategy so client polling runs on a thread you control.

Example fix

// before
executor.shutdownNow(); // interrupts in-flight archive call
// after
archiveCallThread.interrupt() avoided;
volatile boolean cancelled = true; // let the call finish and check flag
Defensive patterns

Strategy: try-catch

Try / catch

try {
    archive.startReplay(recordingId, pos, len, ch, streamId);
} catch (AeronException e) {
    if ("unexpected interrupt".equals(e.getMessage())) {
        Thread.interrupted(); // clear flag; decide retry policy
    }
}

Prevention

When it happens

Trigger: Another thread calls Thread.interrupt() (or an executor shutdownNow()) on the thread blocked in pollForResponse/pollNextResponse waiting for the archive response.

Common situations: 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.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/966bd051b9f0a134. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:2357

        }
        finally
        {
            lock.unlock();
        }
    }

    private void checkDeadline(final long deadlineNs, final String errorMessage, final long correlationId)
    {
        if (deadlineNs - nanoClock.nanoTime() < 0)
        {
            throw new TimeoutException(
                errorMessage + " - correlationId=" + correlationId + " messageTimeout=" +
                SystemUtil.formatDuration(messageTimeoutNs));
        }

        if (Thread.currentThread().isInterrupted())
        {
            throw new AeronException("unexpected interrupt");
        }
    }

    private void pollNextResponse(final long correlationId, final long deadlineNs, final ControlResponsePoller poller)
    {
        idleStrategy.reset();

        while (true)
        {
            final int fragments = poller.poll();

            if (poller.isPollComplete())
            {
                if (poller.templateId() == RecordingSignalEventDecoder.TEMPLATE_ID &&
                    poller.controlSessionId() == controlSessionId)
                {
                    dispatchRecordingSignal(poller);
                    continue;

View on GitHub (pinned to 6d60124e15)