aeron-io/aeron · error · TimeoutException
Archive connect timeout: step= publication= subscription=
Error message
Archive connect timeout: step= publication= subscription=
What it means
During connection establishment the client moves through states (awaiting publication to connect, awaiting the control response subscription image, awaiting responses) with an overall deadline. checkDeadline() compares the deadline against the Aeron context nanoClock and throws a TimeoutException naming the current step plus the publication/subscription channels involved, so you can see exactly which stage stalled.
Solutions
- Verify the archive is running and the controlRequestChannel endpoint matches the archive's control channel.
- Check network reachability (ping/telnet/firewall) for both control request and response channels from the client host.
- Increase ctx.messageTimeoutNs() (the connect deadline derives from it) if the network is slow but functional.
- Ensure the response channel endpoint/port is unique per client and not aliased; check archive logs for received control requests.
Example fix
// before
ctx.messageTimeoutNs(TimeUnit.SECONDS.toNanos(1));
AeronArchive archive = AeronArchive.connect(ctx);
// after
ctx.messageTimeoutNs(TimeUnit.SECONDS.toNanos(5));
ctx.controlRequestChannel("aeron:udp?endpoint=archive-host:8010");
ctx.controlResponseChannel("aeron:udp?endpoint=client-host:8020|alias=client");
AeronArchive archive = AeronArchive.connect(ctx); Defensive patterns
Strategy: retry
Validate before calling
// pre-check reachability of the control endpoint before connect // e.g. DNS resolve + (for TCP) socket probe; for UDP verify config ports differ and are in range
Try / catch
try { archive = AeronArchive.connect(ctx); } catch (TimeoutException e) { log.error("archive connect stalled: " + e.getMessage()); if (attempts++ < 3) { retryWithBackoff(); } else { throw e; } } Prevention
- Verify the archive is running and control endpoint/port match before connecting.
- Give connect() a generous messageTimeoutNs; scale it with network RTT.
- Check archive logs for incoming control requests when timeouts occur.
- Ensure control response endpoints are unique per client instance.
When it happens
Trigger: step=PUB_CONNECT when the control request publication never gets a connected image (archive not running/unreachable); step=AWAIT_CONTROL_RESPONSE_SUBSCRIPTION or AWAIT_CONTROL_RESPONSE_CONNECTION when the response subscription never establishes or no reply arrives within the timeout.
Common situations: Archive process down or wrong control endpoint/port; firewall blocking UDP; controlResponseChannel endpoint not routable from the client host; archive up but on a different cluster/version ignoring requests; very short messageTimeoutNs under load.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- failed to fetch remote recording descriptor
- failed to send recording position request
- failed to get recording position
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/a3da732f17ea6224.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:3978
case AWAIT_CHALLENGE_RESPONSE:
pollForResponse();
break;
case DONE:
return aeronArchive;
default:
break;
}
return null;
}
private void checkDeadline()
{
if (deadlineNs - ctx.aeron().context().nanoClock().nanoTime() < 0)
{
throw new TimeoutException(
"Archive connect timeout: step=" + state +
" publication=" +
(null != archiveProxy ? archiveProxy.publication() : ctx.controlRequestChannel()) +
" subscription=" +
(null != controlResponsePoller ? controlResponsePoller.subscription() :
ctx.controlResponseChannel()));
}
if (Thread.currentThread().isInterrupted())
{
throw new AeronException("unexpected interrupt");
}
}
private void awaitSubscription()
{
final Aeron aeron = ctx.aeron();
if (NULL_VALUE == subscriptionRegistrationId)View on GitHub (pinned to 6d60124e15)