aeron-io/aeron · error · TimeoutException
failed get replay image for sessionId=" +…
Error message
failed get replay image for sessionId=" + (int)srcReplaySessionId + " on channel=" + recordingSubscription.channel()
What it means
Thrown by ReplicationSession.awaitImage() when the replay was acknowledged by the source archive (srcReplaySessionId received) but the local recordingSubscription never saw an Image with that session id within actionTimeoutMs. The source archive started the replay, but the replayed data stream never arrived at the destination's subscription — a data-plane (not control-plane) connectivity or setup problem.
Solutions
- Check the destination Aeron receiver/loss logs for connection attempts on the replay subscription channel — confirm whether any datagrams arrive.
- Verify the replicationChannel URI's endpoint resolves to an address the SOURCE archive can reach, and that all needed UDP ports (including wildcard ranges) are open on the destination host's firewall/security groups.
- Confirm the source archive log shows the replay publication actually being created for the recorded session id; if it errored, fix the source-side cause.
- Ensure both archives agree on media driver configuration (interface, wildcard port range aeron.udp.wildcard.port.range) so the replay connects on the expected endpoint.
- Increase the replication action timeout if the data path is slow to establish (e.g. dynamic resolution on broadcast networks).
Example fix
// before: replication channel endpoint not routable from the source final String replicationChannel = "aeron:udp?endpoint=127.0.0.1:8043"; // after: advertise an address reachable from the source host final String replicationChannel = "aeron:udp?endpoint=10.0.0.5:8043"; archive.replicate(srcRecordingId, replicationChannel, replayStreamId);
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: confirm the destination replay endpoint is reachable from the source host
// (run on the SOURCE host, substituting the replicationChannel endpoint)
// nc -vzu <replicationChannelHost> <replicationChannelPort>
// Also validate the URI parses and has an endpoint:
final ChannelUri uri = ChannelUri.parse(replicationChannel);
if (null == uri.get(CommonContext.ENDPOINT_PARAM_NAME))
{
throw new IllegalArgumentException("replicationChannel must specify an endpoint");
} Try / catch
try
{
archive.replicate(srcRecordingId, replicationChannel, replayStreamId);
}
catch (io.aeron.exceptions.TimeoutException e)
{
if (e.getMessage().contains("failed get replay image"))
{
LOGGER.error("control plane OK but replay DATA path blocked; check firewall/endpoint on " +
replicationChannel, e);
}
throw e;
} Prevention
- Firewall must allow UDP on the data-plane ports, not just the archive control port
- Advertise replication-channel endpoints that are routable FROM the source archive (no localhost/inner-NAT addresses)
- Align aeron.udp.wildcard.port.range on both drivers
- Enable loss/receiver logging and monitor image connection counts in production
When it happens
Trigger: recordingSubscription.imageBySessionId((int)srcReplaySessionId) returns null for actionTimeoutMs; the replay publication on the source cannot connect to the destination's replay subscription because the replicationChannel endpoint is unreachable, blocked by a firewall on a different port than the control channel, or misconfigured (wrong endpoint/ports in the replication channel URI).
Common situations: Firewall permits the archive control port but not the data-plane UDP port(s); replicationChannel URI points at a wrong host/port or an interface that is not routable from the source; source replay fails to start its publication (exhausted stream ids / driver error) after ACKing; wildcard port substitution (replaceEndpointWildcardPort) resolved to an address the source cannot reach; MTU/security groups dropping large UDP flows.
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
- failed to send replay request
- failed get acknowledgement of replay request to: " +…
- ControlSession.RESPONSE_NOT_CONNECTED_MSG + ": " + session
- failed to fetch remote recording descriptor
- not connected
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/14eac0123a9d928c.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/ReplicationSession.java:769
}
private int awaitImage()
{
int workCount = 0;
final Image image = recordingSubscription.imageBySessionId((int)srcReplaySessionId);
if (null != image)
{
this.image = image;
state(null == liveDestination ? State.REPLICATE : State.CATCHUP,
"image.correlationId=" + image.correlationId() +
", image.sessionId=" + image.sessionId() +
", image.joinPosition=" + image.joinPosition());
workCount += 1;
}
else if (epochClock.time() >= (timeOfLastActionMs + actionTimeoutMs))
{
throw new TimeoutException(
"failed get replay image for sessionId=" + (int)srcReplaySessionId +
" on channel=" + recordingSubscription.channel());
}
return workCount;
}
private int replicate()
{
int workCount = 0;
final boolean isClosed = image.isClosed();
final boolean isEndOfStream = image.isEndOfStream();
final long position = image.position();
final boolean isSynced = NULL_POSITION != srcStopPosition && position >= srcStopPosition;
if (isSynced ||
(NULL_POSITION != dstStopPosition && position >= dstStopPosition) ||View on GitHub (pinned to 6d60124e15)