aeron-io/aeron · critical · ClusterException
already in snapshot
Error message
already in snapshot
What it means
The loader is a state machine over SnapshotMarker frames: BEGIN opens the snapshot, SECTION streams entries, END closes it. A second BEGIN while inSnapshot is already true means the stream contains nested or duplicated snapshot start markers, which is invalid. The loader throws rather than silently overwriting state captured from the first BEGIN (appVersion, timeUnit).
Solutions
- Replay exactly one snapshot recording (a single BEGIN/END pair) during recovery
- Re-take the snapshot to replace the corrupted/concatenated recording
- Check archive replay offsets so the stream does not restart inside an already-open snapshot
Defensive patterns
Strategy: validation
Validate before calling
// Ensure exactly one snapshot recording is replayed per recovery
if (recordings.length != 1) { throw new IllegalArgumentException("expected one snapshot recording, got " + recordings.length); } Try / catch
try { loader.load(...); } catch (ClusterException e) { abortRecovery(e); } Prevention
- Never concatenate snapshot recordings
- Replay each recording from position 0
- Re-take snapshots rather than patching broken ones
When it happens
Trigger: onFragment receives a SnapshotMarker with mark=BEGIN while the inSnapshot flag is already true, i.e. two BEGIN markers without an intervening END.
Common situations: Corrupted or concatenated recordings replayed as one snapshot stream, replay starting mid-recording then restarting from the beginning, or a recording tool that stitched snapshots together.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- missing begin snapshot
- unexpected snapshot type
- publication is not connected
- publication is closed
- publication at max position: term-length=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/cafc44f5ee2c6cc8.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ServiceSnapshotLoader.java:102
case SnapshotMarkerDecoder.TEMPLATE_ID:
snapshotMarkerDecoder.wrap(
buffer,
offset + MessageHeaderDecoder.ENCODED_LENGTH,
messageHeaderDecoder.blockLength(),
messageHeaderDecoder.version());
final long typeId = snapshotMarkerDecoder.typeId();
if (SNAPSHOT_TYPE_ID != typeId)
{
throw new ClusterException("unexpected snapshot type: " + typeId);
}
switch (snapshotMarkerDecoder.mark())
{
case BEGIN:
if (inSnapshot)
{
throw new ClusterException("already in snapshot");
}
inSnapshot = true;
appVersion = snapshotMarkerDecoder.appVersion();
timeUnit = ClusterClock.map(snapshotMarkerDecoder.timeUnit());
return Action.CONTINUE;
case END:
if (!inSnapshot)
{
throw new ClusterException("missing begin snapshot");
}
isDone = true;
return Action.BREAK;
case SECTION:
case NULL_VAL:
break;
}View on GitHub (pinned to 6d60124e15)