aeron-io/aeron · critical · ClusterEvent
- joinPosition= than logPosition=
Error message
${state} - joinPosition=${joinPosition}${inequality}than logPosition=${logPosition} What it means
Election.verifyLogJoinPosition guards that the position at which a member is asked to join (or replay) the cluster log exactly equals the member's current logPosition. Aeron requires the log to be joined at the exact committed position so no entries are skipped or duplicated; any mismatch is a consensus/follower state bug and the election is aborted with a ClusterEvent.
Solutions
- Check the reported joinPosition vs logPosition values to see which member state is stale
- Restore the member from a recent snapshot or clean its cluster data directory and rejoin so it recovers via catch-up
- Ensure all members run the same Aeron version and cluster configuration (term-length, service Counters)
- If reproducible, file a bug with the election state trace — a mismatch here usually indicates an internal election bug
Example fix
// before: joining log with a computed position
ctx.logChannel() // joined with joinPosition != election.logPosition
// after: force the member to catch up before joining
if (joinPosition != logPosition) {
// re-enter catch-up / reset from snapshot instead of throwing
electionState(ElectionState.CATCHUP_TRANSITION);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (election.logPosition() != expectedJoinPosition) { /* re-enter catch-up instead of joining */ } Try / catch
try { election.joinLog(joinPosition); } catch (ClusterEvent e) { agent.resetFromSnapshot(); } Prevention
- Keep snapshots and recovery state up to date on every member
- Run identical Aeron versions across the cluster
- Monitor catch-up completion before log join
When it happens
Trigger: During election states such as FOLLOWER_BALLOT, CATCHUP_TRANSITION or LEADER_TRANSITION, Election computes a joinPosition passed to verifyLogJoinPosition; if it differs from this member's logPosition (because of stale snapshot state, a catchup that did not complete, or an internal bookkeeping bug), the exception is thrown.
Common situations: Corrupt or outdated snapshot/recovery state on a member, interrupted catch-up, versions of the cluster members out of sync, or a bug in custom election/consensus-module extensions leading members to disagree on the log position.
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
- logSessionId was null, should always have a value
- invalid newLeadershipTerm - this.appendPosition=
- timeout awaiting commit position
- invalid election state counter code
- joinPosition= expected startPosition=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/93c4597a41628e7a.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/Election.java:1544
logLeadershipTermId = leadershipTermId;
}
private void updateRecordingLogForReplication(
final long leadershipTermId,
final long termBaseLogPosition,
final long logPosition,
final long nowNs)
{
ensureRecordingLogCoherent(leadershipTermId, termBaseLogPosition, logPosition, nowNs);
logLeadershipTermId = leadershipTermId;
}
private void verifyLogJoinPosition(final String state, final long joinPosition)
{
if (joinPosition != logPosition)
{
final String inequality = joinPosition < logPosition ? " less " : " greater ";
throw new ClusterEvent(
state + " - joinPosition=" + joinPosition + inequality + "than logPosition=" + logPosition);
}
}
private boolean hasUpdateIntervalExpired(final long nowNs, final long intervalNs)
{
return hasIntervalExpired(nowNs, timeOfLastUpdateNs, intervalNs);
}
private boolean hasIntervalExpired(
final long nowNs, final long previousTimestampForIntervalNs, final long intervalNs)
{
return (nowNs - previousTimestampForIntervalNs) >= intervalNs;
}
private void logStateChange(
final int memberId,
final ElectionState oldState,View on GitHub (pinned to 6d60124e15)