aeron-io/aeron · error · ClusterException

Live log replay failed

Error message

Live log replay failed (replaySessionId=${liveLogReplaySessionId}): errorMessage=${poller.errorMessage()}, errorCode=${ArchiveException.errorCodeAsString((int)poller.relevantId())}

What it means

When the control poller reports ERROR during live log replay, throwReplayFailedException builds a ClusterException including the replay session id, the archive error message, and the decoded archive error code — i.e. the archive itself refused or failed the replay request.

Solutions

  1. Read errorCode/errorMessage in the exception and inspect archive logs for the underlying cause.
  2. Ensure the log recording still exists on the archive and was not deleted; reseed/restart the backup if the recording is gone.
  3. Check archive max concurrent replays/sessions config and raise it or wait, then retry the backup.
Defensive patterns

Strategy: retry

Validate before calling

// ensure the live log recording exists before starting backup
long recId = ConsensusModule.Configuration.logRecordingId(countersReader);
if (recId == Aeron.NULL_VALUE) { throw new IllegalStateException("no log recording"); }

Try / catch

try { ClusterBackup.launch(ctx); } catch (ClusterException e) { if (e.getMessage().contains("Live log replay failed")) { inspectArchiveLogsAndRetry(); } }

Prevention

When it happens

Trigger: The archive returns an ERROR control response for the replay of the live log recording: e.g. unknown recording id, replay session limits exhausted, recording deleted, or archive-internal failure.

Common situations: Log recording missing from the archive (cleaned up before backup replay); archive at max concurrent replays; permission/disk errors inside the archive.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackupAgent.java:911

                        ControlResponseCode.ERROR == poller.code())
                    {
                        throwReplayFailedException(poller);
                    }
                }
            }
        }
        else
        {
            timeOfLastProgressMs = nowMs;
            state(UPDATE_RECORDING_LOG, nowMs);
        }

        return workCount;
    }

    private void throwReplayFailedException(final ControlResponsePoller poller)
    {
        throw new ClusterException("Live log replay failed (replaySessionId=" + liveLogReplaySessionId + "):" +
            " errorMessage=" + poller.errorMessage() + ", errorCode=" +
            ArchiveException.errorCodeAsString((int)poller.relevantId()));
    }

    private int updateRecordingLog(final long nowMs)
    {
        boolean wasRecordingLogUpdated = false;
        try
        {
            final long snapshotLeadershipTermId = snapshotsRetrieved.isEmpty() ?
                NULL_VALUE : snapshotsRetrieved.get(0).leadershipTermId();

            if (null != leaderLogEntry &&
                recordingLog.isUnknown(leaderLogEntry.leadershipTermId) &&
                leaderLogEntry.leadershipTermId <= snapshotLeadershipTermId)
            {
                recordingLog.appendTerm(
                    liveLogRecordingId,

View on GitHub (pinned to 6d60124e15)