aeron-io/aeron · error · ClusterException

unknown clusterSessionId

Error message

unknown clusterSessionId: <clusterSessionId>

What it means

ClusteredServiceAgent.lookupSession (isSessionOpen-style API) looks up the given clusterSessionId in sessionByIdMap; if absent, it throws ClusterException. Services may only query client sessions the cluster currently knows about — a stale or unknown session id is a programming or lifecycle error.

Solutions

  1. Verify the session id is current: only use clusterSessionId values received in onSessionMessage/onConnect callbacks of the running instance.
  2. Clear persisted session-id caches on service start/snapshot restore and re-learn sessions.
  3. Handle lifecycle: treat closed sessions as gone; do not keep acting on ids after onSessionClose.

Example fix

// before
boolean open = agent.isSessionOpen(staleSessionId);
// after
if (knownSessionIds.contains(staleSessionId)) {
    boolean open = agent.isSessionOpen(staleSessionId);
} else {
    // re-acquire session state or ignore the message
}
Defensive patterns

Strategy: try-catch

Validate before calling

// java: track ids received via service callbacks and check membership first
if (!sessionsSeenSinceStart.contains(clusterSessionId)) {
    // unknown to this instance; skip rather than call the agent API
    return;
}

Try / catch

try {
    isSessionOpen = ctx.isSessionOpen(clusterSessionId);
} catch (ClusterException e) {
    if (e.getMessage().contains("unknown clusterSessionId")) {
        // session is gone or stale; treat as closed, refresh session bookkeeping
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A ClusteredService calling the session-lookup API with a clusterSessionId that has never been opened, already been closed, or belongs to another cluster instance.

Common situations: Caching session ids across snapshots/restarts and reusing them after reconnect; responding to a client whose session was closed concurrently; deserializing a request containing a stale session id.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceAgent.java:330

    public Collection<ClientSession> clientSessions()
    {
        return unmodifiableClientSessions;
    }

    public void forEachClientSession(final Consumer<? super ClientSession> action)
    {
        sessions.forEach(action);
    }

    public boolean closeClientSession(final long clusterSessionId)
    {
        checkForValidInvocation();

        final ContainerClientSession clientSession = sessionByIdMap.get(clusterSessionId);
        if (clientSession == null)
        {
            throw new ClusterException("unknown clusterSessionId: " + clusterSessionId);
        }

        if (clientSession.isClosing())
        {
            return true;
        }

        int attempts = 3;
        do
        {
            if (consensusModuleProxy.closeSession(clusterSessionId))
            {
                clientSession.markClosing();
                return true;
            }
            idle();
        }
        while (--attempts > 0);

View on GitHub (pinned to 6d60124e15)