aeron-io/aeron · warning · TimeoutException
failed to join catchup log as follower
Error message
failed to join catchup log as follower
What it means
TimeoutException (WARN) thrown when the follower subscribed to the catchup replay log but never actually joins the catchup image/log within ctx.leaderHeartbeatTimeoutNs. The subscription was added successfully but no connection or progress on it occurred before the deadline, so the catchup phase fails.
Solutions
- Confirm the leader is alive and its replay service is running; check leader logs for replay errors
- Increase ctx.leaderHeartbeatTimeoutNs() to allow slow replay connects
- Check network path (ports/firewall) between follower and leader for the replay stream
- Restart the member to trigger a fresh election if the leader has since changed
Example fix
// before ctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(10)); // after ctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(60));
Defensive patterns
Strategy: retry
Try / catch
catch (TimeoutException e) {
// catchup join timed out; node should re-canvas; restart member if stuck
memberRestartIfRepeated(e, 3);
} Prevention
- Keep leaderHeartbeatTimeoutNs larger than worst-case replay connect time
- Monitor leader replay service load
- Alert on repeated follower catchup failures
When it happens
Trigger: In FOLLOWER_CATCHUP_AWAIT with the subscription not errored: if the image never connects (or state never advances to FOLLOWER_CATCHUP) before timeOfLastStateChangeNs + leaderHeartbeatTimeoutNs, this is thrown.
Common situations: Leader not replaying (overloaded, dead, or unreachable); network drop after subscription add; leaderHeartbeatTimeoutNs too short for big backlogs; leader's replay service busy.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- failed to send catchup position
- startupCanvassTimeoutNs=
- timeout awaiting commit position
- failed to join catchup log
- failed to join live log as follower
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/cdbed9fe352e65a0.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/Election.java:1078
int workCount = 0;
final Image image = logSubscription.imageBySessionId(logSessionId);
if (null != image)
{
verifyLogJoinPosition("followerCatchupAwait", image.joinPosition());
if (consensusModuleAgent.tryJoinLogAsFollower(image, isLeaderStartup, nowNs))
{
state(FOLLOWER_CATCHUP, nowNs, "");
workCount++;
}
else if (ChannelEndpointStatus.ERRORED == logSubscription.channelStatus())
{
final String message = "failed to add catchup log as follower - " + logSubscription.channel();
throw new ClusterException(message, AeronException.Category.WARN);
}
else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))
{
throw new TimeoutException("failed to join catchup log as follower", AeronException.Category.WARN);
}
}
else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))
{
throw new TimeoutException("failed to join catchup log", AeronException.Category.WARN);
}
return workCount;
}
private int followerCatchup(final long nowNs)
{
int workCount = consensusModuleAgent.catchupPoll(notifiedCommitPosition, nowNs);
if (null == consensusModuleAgent.liveLogDestination() &&
consensusModuleAgent.isCatchupNearLive(max(catchupJoinPosition, notifiedCommitPosition)))
{
addLiveLogDestination();View on GitHub (pinned to 6d60124e15)