aeron-io/aeron · error · ArchiveException

failed to send bounded replay request

Error message

failed to send bounded replay request

What it means

startBoundedReplay sends a BOUNDED_REPLAY request that attaches a limit counter to cap replay length. ArchiveProxy.boundedReplay returning false (publication not connected, offer failed) means the request was never delivered, so the library throws this ArchiveException.

Solutions

  1. Check archive health and control channel connectivity.
  2. Reconnect via AeronArchive.connect and retry the bounded replay.
  3. Retry with backoff to ride out transient backpressure.
  4. Ensure the limitCounterId counter is valid/registered in the same Aeron client before retrying.

Example fix

// before
long sessionId = archive.startBoundedReplay(recId, pos, len, counterId, ch, streamId);

// after
try {
    sessionId = archive.startBoundedReplay(recId, pos, len, counterId, ch, streamId);
} catch (ArchiveException e) {
    archive = AeronArchive.connect(archiveCtx);
    sessionId = archive.startBoundedReplay(recId, pos, len, counterId, ch, streamId);
}
Defensive patterns

Strategy: retry

Validate before calling

if (limitCounterId <= 0) throw new IllegalArgumentException("invalid limitCounterId");
try (AeronArchive ignored = AeronArchive.connect(archiveCtx)) {}

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling startBoundedReplay(recordingId, position, length, limitCounterId, replayChannel, replayStreamId) while the control-request publication is disconnected or backpressured — archive down/restarting, network partition, or a closed control session.

Common situations: Bounded replays used by monitoring/scrubbing tools that run while the archive is under load; control stream backpressure when many clients share one control channel; archive redeployment between issuing and replaying.

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/b35b8c2b4418ba4f. Report an issue: GitHub.

Appendix: source

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

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

            lastCorrelationId = aeron.nextCorrelationId();

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

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

    /**
     * Start a replay for a recording based upon the parameters set in ReplayParams. By default, it will replay
     * all the recording from the start. The ReplayParams is free to be reused when this call completes.
     *
     * @param recordingId    to be replayed.
     * @param replayChannel  to which the replay should be sent.
     * @param replayStreamId to which the replay should be sent.
     * @param replayParams   optional parameters for the replay

View on GitHub (pinned to 6d60124e15)