{"record":{"id":"6d69276b81745c55","repo":"aeron-io/aeron","slug":"invalid-clustersessionid-expected","errorCode":null,"errorMessage":"invalid clusterSessionId= expected=","messagePattern":"invalid clusterSessionId= expected=","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java","lineNumber":679,"sourceCode":"\n    /**\n     * To be called when a new leader event is delivered. This method needs to be called when using the\n     * {@link EgressAdapter} or {@link EgressPoller} rather than {@link #pollEgress()} method.\n     *\n     * @param clusterSessionId which must match {@link #clusterSessionId()}.\n     * @param leadershipTermId that identifies the term for which the new leader has been elected.\n     * @param leaderMemberId   which has become the new leader.\n     * @param ingressEndpoints comma separated list of cluster ingress endpoints to connect to with the leader first.\n     */\n    public void onNewLeader(\n        final long clusterSessionId,\n        final long leadershipTermId,\n        final int leaderMemberId,\n        final String ingressEndpoints)\n    {\n        if (clusterSessionId != this.clusterSessionId)\n        {\n            throw new ClusterException(\n                \"invalid clusterSessionId=\" + clusterSessionId + \" expected=\" + this.clusterSessionId);\n        }\n\n        state(State.AWAIT_NEW_LEADER_CONNECTION, nanoClock.nanoTime() + ctx.messageTimeoutNs());\n\n        this.leadershipTermId = leadershipTermId;\n        this.leaderMemberId = leaderMemberId;\n        sessionMessageHeaderEncoder.leadershipTermId(leadershipTermId);\n\n        CloseHelper.close(publication);\n        if (null == ctx.ingressEndpoints())\n        {\n            publication = addNewLeaderIngressPublication(ctx, ctx.ingressChannel(), ctx.ingressStreamId());\n        }\n        else\n        {\n            ctx.ingressEndpoints(ingressEndpoints);\n            updateMemberEndpoints(ingressEndpoints, leaderMemberId);","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java#L661-L697","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsharedSubscription.poll(handler, 0); // handler.onNewLeader throws on stale session events\n// after\nif (newLeaderClusterSessionId == myClient.clusterSessionId()) { myClient.onNewLeader(...); } else { discardStaleFragment(); }","handlingStrategy":"validation","validationCode":"if (eventClusterSessionId != client.clusterSessionId()) { log.warn(\"stale NewLeaderEvent ignored\"); return; }","typeGuard":null,"tryCatchPattern":"try { client.onNewLeader(leadershipTermId, leaderMemberId, ingressEndpoints); } catch (ClusterException e) { if (e.getMessage().startsWith(\"invalid clusterSessionId=\")) { discardStaleEgressAndReconnect(); } }","preventionTips":["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."],"tags":["cluster","session","consensus","egress"],"backgroundTag":"invalid-argument-value","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"}