aeron-io/aeron · warning · ClusterException
joinPosition= expected startPosition=
Error message
joinPosition=${joinPosition} expected startPosition=${startPosition} What it means
During log replay, LogReplay.doWork locates the replay Image by session id and asserts its joinPosition equals the expected startPosition for the replay. If the image was joined at a different position the replay would deliver wrong entries, so a WARN-category ClusterException is thrown and the replay fails.
Solutions
- Verify the archive contains a recording covering the requested replay startPosition (aeron-archive catalog)
- Restore from a later snapshot so replay can start from a position the recording actually contains
- Ensure the log subscription is bound to the correct log session id and no stale image is reused
- Check archive recording start positions vs the cluster's recovery plan (recoveryPlan)
Example fix
// before: replaying from an arbitrary snapshot position replay(fromPosition); // after: use the recovery plan's snapshot/recording positions RecoveryPlan plan = archiveClient.buildRecoveryPlan(...); replay(plan.snapshotPosition());
Defensive patterns
Strategy: try-catch
Validate before calling
if (image.joinPosition() != replayStartPosition) { /* re-plan recovery from snapshot */ } Try / catch
try { replay.doWork(); } catch (ClusterException e) { /* WARN category: fall back to a later snapshot */ } Prevention
- Ensure archive recordings cover the replay startPosition
- Recover from snapshots listed in the recovery plan
- Avoid reusing stale log subscription images
When it happens
Trigger: Replaying the log after election/snapshot recovery when the archive image for the log session was joined at a position that differs from the replay startPosition — e.g. the archive recording starts later than the requested replay position, or a stale subscription image is picked up.
Common situations: Missing or truncated archive segments so the recording's start position moved forward; racing a new recording image while replaying; misconfigured replay channel/merge in cluster recovery.
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
- invalid position: " + position
- invalid length: " + length
- length must be positive
- fromPosition + " position not aligned to valid fragment
- failed to open recording segment file " + segmentFileName
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/43853299456b4ae1.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/LogReplay.java:88
{
errorHandler.onError(ex);
}
logAdapter.disconnect(errorHandler);
CloseHelper.close(errorHandler, logSubscription);
}
int doWork()
{
int workCount = 0;
if (null == logAdapter.image())
{
final Image image = logSubscription.imageBySessionId(logSessionId);
if (null != image)
{
if (image.joinPosition() != startPosition)
{
throw new ClusterException(
"joinPosition=" + image.joinPosition() + " expected startPosition=" + startPosition,
ClusterException.Category.WARN);
}
logAdapter.image(image);
consensusModuleAgent.awaitServicesReady(
logSubscription.channel(),
logSubscription.streamId(),
logSessionId,
startPosition,
stopPosition,
true,
Cluster.Role.FOLLOWER);
workCount += 1;
}
}
elseView on GitHub (pinned to 6d60124e15)