aeron-io/aeron · error · ClusterEvent
unexpected image close when replaying log: position=
Error message
unexpected image close when replaying log: position=<position>
What it means
While a follower is replaying the log from the archive, the replay image can close prematurely (recording/image ended before reaching stopPosition). The agent throws ClusterEvent to signal the replay cannot be completed, which typically triggers a retry of the log replay or election restart.
Solutions
- Verify the archive recording covering the full log range exists and was not deleted (recording log / aeron-archive tooling).
- Retry the election/replay — the cluster usually re-elects and re-requests the replay.
- Check archive client and network stability between follower and archive/leader.
- Increase archive retention so recordings outlive follower catch-up windows.
Example fix
// before: recordings pruned aggressively archive.markCatalog... delete old recordings while followers still need them // after: retain recordings until all followers have caught up past that position
Defensive patterns
Strategy: retry
Validate before calling
// before requesting replay
if (!archive.hasRecordingForRange(logPosition, stopPosition)) { electDifferentLeader(); } Try / catch
try { agent.doWork(); } catch (ClusterEvent e) { if (e.getMessage().contains("unexpected image close when replaying log")) { requestReplayAgain(); } else { throw e; } } Prevention
- Retain archive recordings until all followers pass their positions.
- Monitor archive recording health on the leader.
- Ensure reliable networking between followers and archive.
When it happens
Trigger: During log replay, logAdapter.isImageClosed() becomes true while commit position is still below stopPosition — the archive replay image ended early because the recording stopped or the archive connection dropped.
Common situations: Archive recording deleted or stopped before all followers caught up; archive agent/network failure severing the replay subscription; leader crashed and its recording became unavailable mid-replay.
Related errors
- cannot live merge without active source recording
- errorCode (variable)
- failed to fetch remote recording descriptor
- failed to get recording position
- failed to list remote recording descriptor
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/72c3178c947b6421.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java:1860
return new LogReplay(archive, logRecordingId, logPosition, appendPosition, logAdapter, ctx);
}
int replayLogPoll(final LogAdapter logAdapter, final long stopPosition)
{
int workCount = 0;
if (ConsensusModule.State.ACTIVE == state || ConsensusModule.State.SUSPENDED == state)
{
logAdapter.poll(stopPosition);
final long position = logAdapter.position();
if (commitPosition.proposeMaxRelease(position))
{
workCount++;
}
else if (logAdapter.isImageClosed() && position < stopPosition)
{
throw new ClusterEvent("unexpected image close when replaying log: position=" + position);
}
}
workCount += consensusModuleAdapter.poll();
return workCount;
}
long logRecordingId()
{
return logRecordingId;
}
void logRecordingId(final long recordingId)
{
if (NULL_VALUE != recordingId)
{
logRecordingId = recordingId;View on GitHub (pinned to 6d60124e15)