aeron-io/aeron · error · ClusterException
failed to add catchup log as follower
Error message
failed to add catchup log as follower - ${channel} What it means
ClusterException (WARN) thrown while a follower waits for its catchup log subscription to connect: the media driver reported the subscription's channel status as ERRORED. The follower could not add the catchup replay image, so the catchup cannot proceed and the election for this member fails.
Solutions
- Inspect the media driver logs for the underlying channel error (e.g. bind failure, unknown host)
- Fix the cluster ingress/log/replay channel endpoints in the member's config so the catchup channel resolves and binds
- Check ports are free and not blocked by firewall between follower and leader
- Restart the node after fixing channel config; the election will be retried
Example fix
// before
.udpChannel("aeron:udp?endpoint=192.168.0.14:20000")
// after (correct, reachable member address)
.udpChannel("aeron:udp?endpoint=192.168.0.14|20000") // verify host:port reachable from leader Defensive patterns
Strategy: validation
Validate before calling
// pre-validate the log/catchup channel URI resolves and interface exists
ChannelUriStringBuilder b = new ChannelUriStringBuilder().media("udp").endpoint(host, port);
if (!networkInterfaceExists(interfaceOf(b.build()))) {
throw new IllegalArgumentException("catchup channel interface missing");
} Try / catch
catch (ClusterException e) {
if (e.getMessage().startsWith("failed to add catchup log")) {
// check driver error log, fix channel config, restart member
}
} Prevention
- Validate channel endpoints/interfaces in config at startup
- Reserve ports to avoid conflicts
- Test multicast/unicast connectivity between members before deployment
When it happens
Trigger: During FOLLOWER_CATCHUP_AWAIT, logSubscription.channelStatus() returns ChannelEndpointStatus.ERRORED, typically because the underlying URI/name resolution/binding of the catchup channel failed in the driver.
Common situations: Invalid or unreachable catchup channel addresses (multi-icast/unicast misconfiguration), driver-side errors like port already in use, network interface names wrong in cluster channel config.
Related errors
- failed to add live log as follower
- Archive.Context.controlChannel must be set
- Archive.Context.controlChannel must be UDP media: uri=
- archive is not connected
- channel error -
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/828759fcca03caed.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/Election.java:1074
}
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++;
}
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);
View on GitHub (pinned to 6d60124e15)