{"record":{"id":"abb5fe2082f5cef9","repo":"aeron-io/aeron","slug":"failed-to-join-live-log-as-follower","errorCode":null,"errorMessage":"failed to join live log as follower","messagePattern":"failed to join live log as follower","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"warning","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/Election.java","lineNumber":1150,"sourceCode":"    }\n\n    private int followerLogAwait(final long nowNs)\n    {\n        int workCount = 0;\n\n        final Image image = logSubscription.imageBySessionId(logSessionId);\n        if (null != image)\n        {\n            verifyLogJoinPosition(\"followerLogAwait\", image.joinPosition());\n            if (consensusModuleAgent.tryJoinLogAsFollower(image, isLeaderStartup, nowNs))\n            {\n                updateRecordingLog(nowNs);\n                state(FOLLOWER_READY, nowNs, \"\");\n                workCount++;\n            }\n            else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))\n            {\n                throw new TimeoutException(\"failed to join live log as follower\", AeronException.Category.WARN);\n            }\n        }\n        else if (ChannelEndpointStatus.ERRORED == logSubscription.channelStatus())\n        {\n            final String message = \"failed to add live log as follower - \" + logSubscription.channel();\n            throw new ClusterException(message, AeronException.Category.WARN);\n        }\n        else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))\n        {\n            throw new TimeoutException(\"failed to join live log\", AeronException.Category.WARN);\n        }\n\n        return workCount;\n    }\n\n    private int followerReady(final long nowNs)\n    {\n        if (consensusPublisher.appendPosition(","sourceCodeStart":1132,"sourceCodeEnd":1168,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/Election.java#L1132-L1168","documentation":"TimeoutException (WARN) thrown when a follower subscribed to the new live log during election but did not connect/join it within ctx.leaderHeartbeatTimeoutNs. The subscription exists but no image connected before the deadline, so the follower cannot transition to FOLLOWER_READY and the election fails for this member.","triggerScenarios":"In FOLLOWER_LIVE_LOG_AWAIT (after adding the live log subscription): if the log image never becomes ready before timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs(), this is thrown.","commonSituations":"Leader's log publication not connected back to the follower (network/firewall), leader changed or died during election, slow driver, leaderHeartbeatTimeoutNs too small for clusters with many members.","solutions":["Verify the leader's log publication endpoint is reachable from the follower (check log channel config and firewall)","Increase ctx.leaderHeartbeatTimeoutNs()","Check media driver logs on both sides for subscription/publication connection errors","Confirm the leader is still the leader; restart the member to redo the election"],"exampleFix":"// before\nctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(10));\n// after\nctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(30));","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (TimeoutException e) {\n    // live log join timed out; election will retry; alert if repeated\n}","preventionTips":["Open log-channel ports between all members","Size leaderHeartbeatTimeoutNs for cluster scale","Watch driver logs for publication connection errors"],"tags":["timeout","live-log","election"],"backgroundTag":"request-timeout","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}