{"record":{"id":"cdbed9fe352e65a0","repo":"aeron-io/aeron","slug":"failed-to-join-catchup-log-as-follower","errorCode":null,"errorMessage":"failed to join catchup log as follower","messagePattern":"failed to join catchup log as follower","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"warning","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/Election.java","lineNumber":1078,"sourceCode":"        int workCount = 0;\n\n        final Image image = logSubscription.imageBySessionId(logSessionId);\n        if (null != image)\n        {\n            verifyLogJoinPosition(\"followerCatchupAwait\", image.joinPosition());\n            if (consensusModuleAgent.tryJoinLogAsFollower(image, isLeaderStartup, nowNs))\n            {\n                state(FOLLOWER_CATCHUP, nowNs, \"\");\n                workCount++;\n            }\n            else if (ChannelEndpointStatus.ERRORED == logSubscription.channelStatus())\n            {\n                final String message = \"failed to add catchup 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 catchup log as follower\", AeronException.Category.WARN);\n            }\n        }\n        else if (nowNs >= (timeOfLastStateChangeNs + ctx.leaderHeartbeatTimeoutNs()))\n        {\n            throw new TimeoutException(\"failed to join catchup log\", AeronException.Category.WARN);\n        }\n\n        return workCount;\n    }\n\n    private int followerCatchup(final long nowNs)\n    {\n        int workCount = consensusModuleAgent.catchupPoll(notifiedCommitPosition, nowNs);\n\n        if (null == consensusModuleAgent.liveLogDestination() &&\n            consensusModuleAgent.isCatchupNearLive(max(catchupJoinPosition, notifiedCommitPosition)))\n        {\n            addLiveLogDestination();","sourceCodeStart":1060,"sourceCodeEnd":1096,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/Election.java#L1060-L1096","documentation":"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.","triggerScenarios":"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.","commonSituations":"Leader not replaying (overloaded, dead, or unreachable); network drop after subscription add; leaderHeartbeatTimeoutNs too short for big backlogs; leader's replay service busy.","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"],"exampleFix":"// before\nctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(10));\n// after\nctx.leaderHeartbeatTimeoutNs(TimeUnit.SECONDS.toNanos(60));","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (TimeoutException e) {\n    // catchup join timed out; node should re-canvas; restart member if stuck\n    memberRestartIfRepeated(e, 3);\n}","preventionTips":["Keep leaderHeartbeatTimeoutNs larger than worst-case replay connect time","Monitor leader replay service load","Alert on repeated follower catchup failures"],"tags":["timeout","log-catchup","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"}