aeron-io/aeron · critical · ClusterException
Extension subscription joinPosition
Error message
Extension subscription joinPosition (<joinPosition>) does not match logPosition (<logPosition>)
What it means
When a follower becomes leader it attaches an extension subscription to receive the remainder of the log from the previous leader. The image's joinPosition must equal the node's current logPosition; if not, the log continuation would leave a gap or overlap, so the agent throws rather than corrupting the log.
Solutions
- Ensure the node replays logs fully from the archive before attempting leadership extension.
- Check for split-brain: verify quorum and remove any falsely-elected leader.
- Confirm archive/log channel configurations are identical across all cluster nodes.
- Restart the node from a consistent snapshot so its logPosition aligns with the cluster.
Example fix
// before: election triggered while replay incomplete
// after: wait for replay to finish before offering leadership
while (replayPosition < stopPosition) { agent.doWork(); } Defensive patterns
Strategy: validation
Validate before calling
// after replay, before election completes
long joinPos = subscription.imageAtIndex(0).joinPosition();
if (joinPos != consensusModule.logPosition()) { rejoinElection(); } Try / catch
try { agent.doWork(); } catch (ClusterException e) { if (e.getMessage().contains("joinPosition") && e.getMessage().contains("logPosition")) { triggerElectionRestart(); } else { throw e; } } Prevention
- Ensure full archive replay before leadership transitions.
- Eliminate split-brain risks with correct quorum configuration.
- Keep log/archive channels consistent across nodes.
When it happens
Trigger: During leader election/extension, subscription.imageAtIndex(0).joinPosition() differs from the local logPosition — the incoming image starts at a different position than where this node's replay ended.
Common situations: Split-brain or archived-log truncation leaving nodes at divergent positions; archive replay ended at a different position than the new leader is streaming from; misconfigured archive/log channels causing the wrong image to be joined.
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
- Cluster log must be contiguous for active log event…
- Cluster log must be contiguous for joining image…
- invalid newLeadershipTerm - this.appendPosition=
- active counter not found
- Aeron client must use a RethrowingErrorHandler
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/7d1220f34fecd1d2.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java:1732
connectLeaderLogSubscriptionForExtension(logPosition);
}
private void connectLeaderLogSubscriptionForExtension(final long logPosition)
{
if (null != consensusModuleExtension)
{
final Subscription subscription = aeron.addSubscription(localLogChannel, ctx.logStreamId());
idleStrategy.reset();
while (0 == subscription.imageCount())
{
idle();
}
final long joinPosition = subscription.imageAtIndex(0).joinPosition();
if (joinPosition != logPosition)
{
throw new ClusterException(
"Extension subscription " +
"joinPosition (" + joinPosition + ") does not match logPosition (" + logPosition + ")");
}
this.extensionLeaderSubscription = subscription;
}
}
void liveLogDestination(final String liveLogDestination)
{
this.liveLogDestination = liveLogDestination;
}
String liveLogDestination()
{
return liveLogDestination;
}
View on GitHub (pinned to 6d60124e15)