aeron-io/aeron · error · ClusterException
invalid clusterSessionId= expected=
Error message
invalid clusterSessionId= expected=
What it means
onNewLeader receives a NewLeaderEvent from the cluster and validates that the event's clusterSessionId matches the session id this client established. A mismatch means the event belongs to a different session (stale or cross-wired egress image), so the library throws ClusterException to prevent the client from adopting the wrong leader session state.
Solutions
- Ensure each AeronCluster client has its own exclusive egress subscription; do not share egress images between clients or sessions.
- Drain/discard fragments from the previous session before processing events for a new connection.
- Reconnect the client (connect()) so clusterSessionId and egress image are established together.
- Catch ClusterException in egress handlers and log the session mismatch to diagnose subscription sharing.
Example fix
// before
sharedSubscription.poll(handler, 0); // handler.onNewLeader throws on stale session events
// after
if (newLeaderClusterSessionId == myClient.clusterSessionId()) { myClient.onNewLeader(...); } else { discardStaleFragment(); } Defensive patterns
Strategy: validation
Validate before calling
if (eventClusterSessionId != client.clusterSessionId()) { log.warn("stale NewLeaderEvent ignored"); return; } Try / catch
try { client.onNewLeader(leadershipTermId, leaderMemberId, ingressEndpoints); } catch (ClusterException e) { if (e.getMessage().startsWith("invalid clusterSessionId=")) { discardStaleEgressAndReconnect(); } } Prevention
- Never share egress subscriptions between AeronCluster clients.
- Create a fresh egress subscription per connection.
- Drain or drop fragments queued from a previous session before reconnecting.
When it happens
Trigger: Calling onNewLeader() (via onFragment/onControlledFragment egress processing) when the incoming NewLeaderEvent's clusterSessionId differs from the client's clusterSessionId — e.g. egress from a previous session still queued during reconnect, or misconfigured egress subscription receiving another client's events.
Common situations: Reusing an egress Subscription or Image across AeronCluster reconnects; sharing a subscription between multiple cluster clients; processing stale buffered fragments after the old session was closed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ConsensusModule.Context.clusterMembers must be set
- logSessionId was null, should always have a value
- expected cluster egress…
- not found in
- ${eventCode}: ${detail}
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/6d69276b81745c55.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java:679
/**
* To be called when a new leader event is delivered. This method needs to be called when using the
* {@link EgressAdapter} or {@link EgressPoller} rather than {@link #pollEgress()} method.
*
* @param clusterSessionId which must match {@link #clusterSessionId()}.
* @param leadershipTermId that identifies the term for which the new leader has been elected.
* @param leaderMemberId which has become the new leader.
* @param ingressEndpoints comma separated list of cluster ingress endpoints to connect to with the leader first.
*/
public void onNewLeader(
final long clusterSessionId,
final long leadershipTermId,
final int leaderMemberId,
final String ingressEndpoints)
{
if (clusterSessionId != this.clusterSessionId)
{
throw new ClusterException(
"invalid clusterSessionId=" + clusterSessionId + " expected=" + this.clusterSessionId);
}
state(State.AWAIT_NEW_LEADER_CONNECTION, nanoClock.nanoTime() + ctx.messageTimeoutNs());
this.leadershipTermId = leadershipTermId;
this.leaderMemberId = leaderMemberId;
sessionMessageHeaderEncoder.leadershipTermId(leadershipTermId);
CloseHelper.close(publication);
if (null == ctx.ingressEndpoints())
{
publication = addNewLeaderIngressPublication(ctx, ctx.ingressChannel(), ctx.ingressStreamId());
}
else
{
ctx.ingressEndpoints(ingressEndpoints);
updateMemberEndpoints(ingressEndpoints, leaderMemberId);View on GitHub (pinned to 6d60124e15)