aeron-io/aeron · error · ArchiveEvent

response publication is closed: " + session

Error message

response publication is closed: " + session

What it means

ControlResponseProxy.checkResult throws ArchiveEvent (Category.ERROR) when the control response publication offer returns Publication.CLOSED, meaning the response publication has been closed and no further control responses can be sent on this session. The session is aborted as part of the throw.

Solutions

  1. Do not use a control session after it has been closed; check session state (isClosed) before sending responses
  2. Fix races where conductor close and response sends overlap; serialize sends through the conductor thread as Aeron requires
  3. On the client, reconnect with a new control session since the old response publication cannot be revived
  4. Review shutdown ordering so pending responses are flushed before the session is closed

Example fix

// before
if (!controlSession.isClosed())
{
    controlResponseProxy.sendResponse(...);
}
else
{
    controlResponseProxy.sendResponse(...); // throws: publication closed
}
// after
if (!controlSession.isClosed())
{
    controlResponseProxy.sendResponse(...);
}
else
{
    // skip response; session already terminated
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (controlSession == null || controlSession.isClosed()) { return; /* skip send; session terminated */ }

Type guard

boolean canSend(ControlSession s) { return s != null && !s.isClosed(); }

Try / catch

try { proxy.sendDescriptor(correlationId, descriptorBuffer); }
catch (ArchiveEvent e)
{
    if (e.getMessage().startsWith("response publication is closed")) { /* session dead: stop sending */ }
    else { throw e; }
}

Prevention

When it happens

Trigger: Calling sendDescriptor, sendResponse, or send on ControlResponseProxy after the session's response Publication was closed (session shutdown, conductor closing the session, or explicit close of the control session/publication).

Common situations: Archive conductor closed the control session (timeout or client disconnect) while a send was still queued on another thread; race between session close and a final response; archive shutdown in progress while requests still arriving.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/ControlResponseProxy.java:253

            checkResult(session, position);
        }
        while (--attempts > 0);

        return false;
    }

    private static void checkResult(final ControlSession session, final long result)
    {
        if (result == Publication.NOT_CONNECTED)
        {
            session.abort(ControlSession.RESPONSE_NOT_CONNECTED_MSG);
            throw new ArchiveEvent(ControlSession.RESPONSE_NOT_CONNECTED_MSG + ": " + session);
        }

        if (result == Publication.CLOSED)
        {
            session.abort("control response publication is closed");
            throw new ArchiveEvent("response publication is closed: " + session, AeronException.Category.ERROR);
        }

        if (result == Publication.MAX_POSITION_EXCEEDED)
        {
            session.abort("control response publication is at max position");
            throw new ArchiveEvent(
                "response publication is at max position: " + session, AeronException.Category.ERROR);
        }
    }

    private void logSendResponse(final DirectBuffer buffer, final int offset, final int length)
    {
        ArchiveTracing.traceControlResponse(buffer, offset, length);
    }

    private void logSendSignal(final DirectBuffer buffer, final int offset, final int length)
    {
        ArchiveTracing.traceRecordingSignal(buffer, offset, length);

View on GitHub (pinned to 6d60124e15)