aeron-io/aeron · critical · ClusterException

logSessionId was null, should always have a value

Error message

logSessionId was null, should always have a value

What it means

ConsensusPublisher.newLeadershipTerm refuses to send a NewLeadershipTerm message when logSessionId is NULL_SESSION_ID. Every leadership term must have a concrete log session id so followers can attach to the leader's log; null here means internal state was not initialized.

Solutions

  1. Ensure a valid snapshot/log exists so the leader can establish a real logSessionId before elections complete
  2. Restore the cluster mark file and snapshot together from the same backup
  3. Upgrade Aeron — some early versions had election edge cases leaving logSessionId null
  4. Report/reproduce with Aeron maintainers if it recurs on current versions; this indicates internal state corruption

Example fix

// before: starting election with a wiped mark file (no log session)
ClusterException: logSessionId was null, should always have a value
// after: restore mark file + snapshot from backup so the term has a valid logSessionId, or bootstrap the cluster cleanly (fresh cluster dir)
Defensive patterns

Strategy: try-catch

Validate before calling

// Before driving an election, verify a real log session exists
if (clusterMarkFile.logSessionId() == CommonContext.NULL_SESSION_ID) {
    // restore mark file + snapshot from consistent backup or bootstrap fresh
}

Try / catch

try {
    election.start();
} catch (ClusterException e) {
    if (e.getMessage().contains("logSessionId was null")) {
        throw new IllegalStateException("Cluster state not initialized — restore mark file/snapshot from the same backup", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An election path calls newLeadershipTerm before the leader has assigned/learned a valid logSessionId (e.g. leadership term initialized without a log session), so the NULL sentinel is passed through.

Common situations: Cluster recovering from an election with a stale/zeroed mark file; bug-level states after failed log replication where the session id was never established; mis-restored cluster mark files.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusPublisher.java:196

        final long leadershipTermId,
        final long termBaseLogPosition,
        final long logPosition,
        final long commitPosition,
        final long leaderRecordingId,
        final long timestamp,
        final int leaderMemberId,
        final int logSessionId,
        final int appVersion,
        final boolean isStartup)
    {
        if (null == publication)
        {
            return;
        }

        if (CommonContext.NULL_SESSION_ID == logSessionId)
        {
            throw new ClusterException("logSessionId was null, should always have a value");
        }

        final int length = MessageHeaderEncoder.ENCODED_LENGTH + NewLeadershipTermEncoder.BLOCK_LENGTH;

        int attempts = SEND_ATTEMPTS;
        do
        {
            final long position = publication.tryClaim(length, bufferClaim);
            if (position > 0)
            {
                newLeadershipTermEncoder
                    .wrapAndApplyHeader(bufferClaim.buffer(), bufferClaim.offset(), messageHeaderEncoder)
                    .logLeadershipTermId(logLeadershipTermId)
                    .nextLeadershipTermId(nextLeadershipTermId)
                    .nextTermBaseLogPosition(nextTermBaseLogPosition)
                    .nextLogPosition(nextLogPosition)
                    .leadershipTermId(leadershipTermId)
                    .termBaseLogPosition(termBaseLogPosition)

View on GitHub (pinned to 6d60124e15)