{"record":{"id":"7dd0816cacbc1968","repo":"aeron-io/aeron","slug":"snapshot-ended-unexpectedly-image-consensusmoduleagent","errorCode":null,"errorMessage":"snapshot ended unexpectedly: <image>","messagePattern":"snapshot ended unexpectedly: <image>","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"critical","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java","lineNumber":2814,"sourceCode":"        {\n            final Image image = awaitImage(sessionId, subscription);\n            final ConsensusModuleSnapshotAdapter adapter = new ConsensusModuleSnapshotAdapter(image, this);\n\n            idleStrategy.reset();\n            while (true)\n            {\n                final int fragments = adapter.poll();\n                if (adapter.isDone())\n                {\n                    break;\n                }\n\n                if (0 == fragments)\n                {\n                    pollArchiveEvents();\n                    if (image.isClosed())\n                    {\n                        throw new ClusterException(\"snapshot ended unexpectedly: \" + image);\n                    }\n                }\n\n                idle(fragments);\n            }\n\n            for (final PendingServiceMessageTracker tracker : pendingServiceMessageTrackers)\n            {\n                tracker.verify();\n                tracker.reset();\n            }\n\n            if (null != consensusModuleExtension)\n            {\n                consensusModuleExtension.onStart(this, image);\n            }\n        }\n","sourceCodeStart":2796,"sourceCodeEnd":2832,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java#L2796-L2832","documentation":"While replaying a standby snapshot from the archive, the agent polls fragments and expects the image to deliver data until completion. If polling returns no fragments and the image is closed, the snapshot stream terminated early and ClusterException is thrown because the snapshot is incomplete.","triggerScenarios":"Thrown during snapshot polling when image.poll() returns 0 fragments, archive events were polled, and image.isClosed() is true before the snapshot replay finished.","commonSituations":"Archive service restarted mid-replay; snapshot recording deleted or expired; network drop to the archive; archive storage failure corrupting or truncating the recording.","solutions":["Check Archive service logs for recording or replay errors at the failure time","Verify the snapshot recording still exists in the archive catalogue","Inspect network connectivity between the cluster node and the archive","Recovery will use an earlier snapshot; if none is valid, reseed the node from scratch or from a live leader"],"exampleFix":"// before: replaying from an archive session that is torn down mid-transfer\n// (no retry / integrity check)\n\n// after: validate snapshot availability before joining\nif (!archive.listRecording(recordingId, 0, 1))\n{\n    throw new ClusterException(\"snapshot recording missing: \" + recordingId);\n}","handlingStrategy":"retry","validationCode":"// verify the snapshot recording is fully available before replay\nif (!archive.listRecording(recordingId, 0, 1))\n{\n    throw new IllegalStateException(\"snapshot recording missing: \" + recordingId);\n}","typeGuard":null,"tryCatchPattern":"catch (ClusterException e)\n{\n    if (e.getMessage().startsWith(\"snapshot ended unexpectedly\"))\n    {\n        log.error(\"snapshot replay interrupted: {}\", e.getMessage());\n        // recovery proceeds from an earlier snapshot or the live leader\n    }\n    throw e;\n}","preventionTips":["Keep the Archive service highly available and monitored","Do not delete snapshot recordings referenced by the recording log","Ensure reliable network to the archive endpoints","Take snapshots frequently so a corrupt one costs little recovery time"],"tags":["aeron","cluster","snapshot","archive","replay"],"backgroundTag":"broken-pipe","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}