aeron-io/aeron · warning · TimeoutException

failed to send catchup position

Error message

failed to send catchup position

What it means

TimeoutException (WARN) thrown in Election.followerCatchupInit when the follower fails to successfully send its catchup position request to the (candidate) leader within ctx.leaderHeartbeatTimeoutNs. The follower needs to replay missing log entries but could not deliver the request to the leader's replayPublication before the deadline.

Solutions

  1. Check connectivity to the candidate leader on the cluster/replay channels
  2. Increase ctx.leaderHeartbeatTimeoutNs() to give publications time to connect
  3. Verify the leader is still up; retry the election by restarting the node or letting the timeout re-canvas
  4. Check that leader's replay service is not saturated by other catchup requests

Example fix

// before
.clusterContext(ctx -> ctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(10)))
// after
.clusterContext(ctx -> ctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(30)))
Defensive patterns

Strategy: retry

Validate before calling

// verify leader reachability before/at cluster startup
if (!isHostReachable(leaderHost, replayPort)) {
    LOG.warn("leader replay endpoint unreachable; catchup will likely time out");
}

Try / catch

catch (TimeoutException e) {
    // follower re-canvas: retry is built-in; surface metric catchup_send_timeouts++
}

Prevention

When it happens

Trigger: Follower in FOLLOWER_CATCHUP_INIT tries to send a catchup position to the leader each doWork tick; if the send keeps failing (publication not connected) and timeOfLastStateChangeNs + leaderHeartbeatTimeoutNs elapses, this is thrown.

Common situations: Leader went down mid-election; network partition; leader replay publication not yet connected because the leader is overloaded; leaderHeartbeatTimeoutNs too small when starting large clusters.

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


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/ec570f4034e06bcc. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/Election.java:1052

            {
                final int i = resolvedEndpoint.lastIndexOf(':');
                catchupEndpoint = endpoint.substring(0, endpoint.length() - 2) + resolvedEndpoint.substring(i);
            }
        }
        else
        {
            catchupEndpoint = endpoint;
        }

        if (null != catchupEndpoint && sendCatchupPosition(catchupEndpoint))
        {
            timeOfLastUpdateNs = nowNs;
            consensusModuleAgent.catchupInitiated(nowNs);
            state(FOLLOWER_CATCHUP_AWAIT, nowNs, "");
        }
        else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))
        {
            throw new TimeoutException("failed to send catchup position", AeronException.Category.WARN);
        }

        return 1;
    }

    private int followerCatchupAwait(final long nowNs)
    {
        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++;
            }

View on GitHub (pinned to 6d60124e15)