aeron-io/aeron · warning · TimeoutException

ready follower failed to notify leader

Error message

ready follower failed to notify leader

What it means

TimeoutException (WARN) thrown in Election.followerReady: the follower believes it is ready and repeatedly sends its readiness notification to the leader, but the leader never acknowledges (election never completes) within ctx.leaderHeartbeatTimeoutNs. The follower gives up on this election attempt.

Solutions

  1. Check the elected leader's logs and health; it likely crashed or lost connectivity
  2. Verify network reachability between follower and leader control channels
  3. Increase ctx.leaderHeartbeatTimeoutNs()
  4. Ensure the cluster maintains quorum (enough members up) so the leader can finish the election

Example fix

// before
.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(10))
// after
.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(30))
Defensive patterns

Strategy: retry

Try / catch

catch (TimeoutException e) {
    // leader never acked readiness; cluster will re-canvas; alert if repeated
}

Prevention

When it happens

Trigger: In FOLLOWER_READY state each doWork tick sends an election vote/ready message to the leader; if consensusModuleAgent.electionComplete() is never triggered (no leader ack) before timeOfLastStateChangeNs + leaderHeartbeatTimeoutNs, this is thrown.

Common situations: Leader crashed right after winning the vote; leader's ingress channel to followers unreachable; leader overloaded and dropping control messages; leaderHeartbeatTimeoutNs too tight; quorum lost so leader cannot complete election.

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/f0e5666d015d2bc6. Report an issue: GitHub.

Appendix: source

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

        else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))
        {
            throw new TimeoutException("failed to join live log", AeronException.Category.WARN);
        }

        return workCount;
    }

    private int followerReady(final long nowNs)
    {
        if (consensusPublisher.appendPosition(
            leaderMember.publication(), leadershipTermId, logPosition, thisMember.id(), APPEND_POSITION_FLAG_NONE))
        {
            consensusModuleAgent.electionComplete(nowNs);
            state(CLOSED, nowNs, "");
        }
        else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))
        {
            throw new TimeoutException("ready follower failed to notify leader", AeronException.Category.WARN);
        }

        return 1;
    }

    private void placeVote(final long candidateTermId, final int candidateId, final boolean vote)
    {
        final ClusterMember candidate = clusterMemberByIdMap.get(candidateId);
        if (null != candidate)
        {
            consensusPublisher.placeVote(
                candidate.publication(),
                candidateTermId,
                logLeadershipTermId,
                appendPosition,
                candidateId,
                thisMember.id(),
                vote);

View on GitHub (pinned to 6d60124e15)