aeron-io/aeron · error · ClusterException

already in snapshot

Error message

already in snapshot

What it means

A BEGIN snapshot marker arrived while the adapter is already inside a snapshot (inSnapshot == true). Snapshot streams must contain exactly one BEGIN/END pair; nested BEGINs indicate a corrupt or malformed snapshot stream.

Solutions

  1. Restore from a verified backup snapshot recording
  2. Inspect the recording with aeron-archive tooling to find spurious BEGIN markers
  3. Re-take a snapshot on a healthy leader and restart from it
  4. Remove manual edits/splices from the archive catalog

Example fix

// before: replaying a spliced/corrupt recording
ClusterException: already in snapshot
// after
RecordingArchive.verifySnapshot(recordingId); // or re-snapshot on a healthy leader, then load the new snapshot
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check the recording is an intact single snapshot before replay
// e.g. inspect first/last frames for a single BEGIN/END pair; verify recording length matches catalog

Try / catch

try {
    snapshotPlayer.load(recordingId, ...);
} catch (ClusterException e) {
    if ("already in snapshot".equals(e.getMessage())) {
        // mark recording corrupt, restore from backup
        restoreFromBackup();
    } else { throw e; }
}

Prevention

When it happens

Trigger: Replaying a recording that contains two consecutive BEGIN markers without an intervening END — typically a corrupted, duplicated, or wrongly spliced snapshot recording.

Common situations: Archive corruption or manual concatenation of recordings; replaying a partially written or wrongly cataloged recording as a snapshot; custom tooling appending extra snapshot entries.

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


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleSnapshotAdapter.java:105

            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;

                        listener.onLoadBeginSnapshot(
                            snapshotMarkerDecoder.appVersion(),
                            ClusterClock.map(snapshotMarkerDecoder.timeUnit()),
                            buffer,
                            offset,
                            length);
                        return Action.CONTINUE;

                    case END:
                        if (!inSnapshot)
                        {
                            throw new ClusterException("missing begin snapshot");
                        }
                        listener.onLoadEndSnapshot(buffer, offset, length);
                        isDone = true;

View on GitHub (pinned to 6d60124e15)