aeron-io/aeron · error · ArchiveException

Unknown session or token timeout for replayToken=" +…

Error message

Unknown session or token timeout for replayToken=" + replayToken

What it means

When a connect request arrives on a MDC control-mode=response channel with a replayToken, the adapter looks up the corresponding replay session in the archive conductor via getReplaySession(replayToken, recordingId). If no session is registered for that token (unknown token or the token timed out), the connection cannot be correlated and an ArchiveException is thrown.

Solutions

  1. Use the replay token promptly after requesting the replay; if it expired, issue a new startReplay call to obtain a fresh token.
  2. Ensure the connect goes to the same archive instance that issued the token (no cross-node routing unless state is shared).
  3. Verify the recordingId paired with the token matches the replay session that was started.
  4. Check archive conductor logs for session expiry to confirm a timeout versus an unknown token.

Example fix

// before
long token = staleTokenFromPreviousRun;
archive.connect(uri, token);
// after
long token = archive.startReplay(recordingId, position, length, replayChannel, replayStreamId);
archive.connect(uri, token); // use immediately
Defensive patterns

Strategy: retry

Validate before calling

// use the token immediately after obtaining it
long token = archive.startReplay(recId, pos, len, ch, streamId);
if (token == Aeron.NULL_VALUE) throw new IllegalStateException("no token issued");

Try / catch

try {
    controlResponsePoller.resubmitResponseChannelSetup(uri, token);
} catch (ArchiveException e) {
    if (e.getMessage().startsWith("Unknown session")) {
        token = archive.startReplay(recId, pos, len, ch, streamId); // re-issue
    }
}

Prevention

When it happens

Trigger: Calling ArchiveClient with a replayToken whose replay session has already ended or was never created on that archive; reusing a token after its timeout; using a token issued by a different archive instance; long delay between token issuance and connect so the conductor's replay session expired.

Common situations: Client retries a connect long after the original replay finished; load balancer routes the connect to a different archive node than the one that issued the token; token typed/copied incorrectly; slow startup so the replay session timed out before connect.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/ControlSessionAdapter.java:1180

        }
    }

    private ControlSession setupSessionAndChannelForReplay(
        final ChannelUri channelUri,
        final long replayToken,
        final long recordingId,
        final long correlationId,
        final long controlSessionId,
        final int templateId,
        final Image image)
    {
        final ControlSession controlSession;
        if (channelUri.hasControlModeResponse() && Aeron.NULL_VALUE != replayToken)
        {
            controlSession = conductor.getReplaySession(replayToken, recordingId);
            if (null == controlSession)
            {
                throw new ArchiveException("Unknown session or token timeout for replayToken=" + replayToken);
            }

            channelUri.put(RESPONSE_CORRELATION_ID_PARAM_NAME, Long.toString(image.correlationId()));
        }
        else
        {
            controlSession = getControlSession(correlationId, controlSessionId, templateId, image);
        }
        return controlSession;
    }

    private ControlSession getControlSession(
        final long correlationId, final long controlSessionId, final int templateId, final Image image)
    {
        final SessionInfo info = controlSessionByIdMap.get(controlSessionId);
        if (null != info)
        {
            if (info.image != image)

View on GitHub (pinned to 6d60124e15)