{"record":{"id":"076562ea331284ca","repo":"aeron-io/aeron","slug":"logsessionid-was-null-should-always-have-a-value","errorCode":null,"errorMessage":"logSessionId was null, should always have a value","messagePattern":"logSessionId was null, should always have a value","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"critical","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusPublisher.java","lineNumber":196,"sourceCode":"        final long leadershipTermId,\n        final long termBaseLogPosition,\n        final long logPosition,\n        final long commitPosition,\n        final long leaderRecordingId,\n        final long timestamp,\n        final int leaderMemberId,\n        final int logSessionId,\n        final int appVersion,\n        final boolean isStartup)\n    {\n        if (null == publication)\n        {\n            return;\n        }\n\n        if (CommonContext.NULL_SESSION_ID == logSessionId)\n        {\n            throw new ClusterException(\"logSessionId was null, should always have a value\");\n        }\n\n        final int length = MessageHeaderEncoder.ENCODED_LENGTH + NewLeadershipTermEncoder.BLOCK_LENGTH;\n\n        int attempts = SEND_ATTEMPTS;\n        do\n        {\n            final long position = publication.tryClaim(length, bufferClaim);\n            if (position > 0)\n            {\n                newLeadershipTermEncoder\n                    .wrapAndApplyHeader(bufferClaim.buffer(), bufferClaim.offset(), messageHeaderEncoder)\n                    .logLeadershipTermId(logLeadershipTermId)\n                    .nextLeadershipTermId(nextLeadershipTermId)\n                    .nextTermBaseLogPosition(nextTermBaseLogPosition)\n                    .nextLogPosition(nextLogPosition)\n                    .leadershipTermId(leadershipTermId)\n                    .termBaseLogPosition(termBaseLogPosition)","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusPublisher.java#L178-L214","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure a valid snapshot/log exists so the leader can establish a real logSessionId before elections complete","Restore the cluster mark file and snapshot together from the same backup","Upgrade Aeron — some early versions had election edge cases leaving logSessionId null","Report/reproduce with Aeron maintainers if it recurs on current versions; this indicates internal state corruption"],"exampleFix":"// before: starting election with a wiped mark file (no log session)\nClusterException: logSessionId was null, should always have a value\n// after: restore mark file + snapshot from backup so the term has a valid logSessionId, or bootstrap the cluster cleanly (fresh cluster dir)","handlingStrategy":"try-catch","validationCode":"// Before driving an election, verify a real log session exists\nif (clusterMarkFile.logSessionId() == CommonContext.NULL_SESSION_ID) {\n    // restore mark file + snapshot from consistent backup or bootstrap fresh\n}","typeGuard":null,"tryCatchPattern":"try {\n    election.start();\n} catch (ClusterException e) {\n    if (e.getMessage().contains(\"logSessionId was null\")) {\n        throw new IllegalStateException(\"Cluster state not initialized — restore mark file/snapshot from the same backup\", e);\n    }\n    throw e;\n}","preventionTips":["Back up mark file and snapshot together, always restore together","Never zero out the cluster mark file manually","Bootstrap new clusters cleanly rather than editing state files"],"tags":["aeron","cluster","election","consensus"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}