aeron-io/aeron · error · ArchiveException

failed to send replay request

Error message

failed to send replay request

What it means

startReplay issues a REPLAY control request via ArchiveProxy.replay. The proxy returns false when the control-request publication is not connected or the offer fails, meaning the replay request never reached the archive. The client throws this ArchiveException before polling for the replay session id.

Solutions

  1. Confirm the archive is running and the control channel is connected.
  2. Re-establish the AeronArchive session and retry startReplay.
  3. Retry with backoff for transient backpressure on the control stream.
  4. Verify replayChannel/replayStreamId arguments before retrying to rule out client-side config errors.

Example fix

// before
long sessionId = archive.startReplay(recordingId, pos, len, replayChannel, streamId);

// after
long sessionId;
try {
    sessionId = archive.startReplay(recordingId, pos, len, replayChannel, streamId);
} catch (ArchiveException e) {
    archive = AeronArchive.connect(archiveCtx);
    sessionId = archive.startReplay(recordingId, pos, len, replayChannel, streamId);
}
Defensive patterns

Strategy: retry

Validate before calling

// validate inputs and connectivity before startReplay
if (recordingId <= 0 || length < 0) throw new IllegalArgumentException("bad replay args");
try (AeronArchive ignored = AeronArchive.connect(archiveCtx)) {}

Type guard

boolean connected(AeronArchive a) { return a != null && !a.isClosed() && a.state() == AeronArchive.State.CONNECTED; }

Try / catch

try {
    long sid = archive.startReplay(recordingId, pos, len, ch, streamId);
} catch (ArchiveException e) {
    archive = AeronArchive.connect(archiveCtx);
    retryWithBackoff(() -> archive.startReplay(recordingId, pos, len, ch, streamId));
}

Prevention

When it happens

Trigger: Calling startReplay(recordingId, position, length, replayChannel, replayStreamId) with the archive control channel disconnected, backpressured, or the control session publication closed (archive restart, network fault).

Common situations: Replay pipelines started right after archive failover; replayChannel URI typos causing downstream failures that cascade into control-channel disconnects; long-running clients whose control session timed out.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/7ebbbeef0d06cff9. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:1046

    {
        lock.lock();
        try
        {
            ensureConnected();
            ensureNotReentrant();

            lastCorrelationId = aeron.nextCorrelationId();

            if (!archiveProxy.replay(
                recordingId,
                position,
                length,
                replayChannel,
                replayStreamId,
                lastCorrelationId,
                controlSessionId))
            {
                throw new ArchiveException("failed to send replay request");
            }

            return pollForResponse(lastCorrelationId);
        }
        finally
        {
            lock.unlock();
        }
    }

    /**
     * Start a replay for a length in bytes of a recording from a position bounded by a position counter.
     * If the position is {@link #NULL_POSITION} then the stream will be replayed from the start.
     * <p>
     * The lower 32-bits of the returned value contains the {@link Image#sessionId()} of the received replay. All
     * 64-bits are required to uniquely identify the replay when calling {@link #stopReplay(long)}. The lower 32-bits
     * can be obtained by casting the {@code long} value to an {@code int}.
     *

View on GitHub (pinned to 6d60124e15)