{"record":{"id":"7e60e3d277bda2de","repo":"aeron-io/aeron","slug":"unexpected-snapshot-type-typeid-servicesnapshotloader","errorCode":null,"errorMessage":"unexpected snapshot type: ${typeId}","messagePattern":"unexpected snapshot type: (.+?)","errorType":"console","errorClass":"ClusterException","httpStatus":null,"severity":"critical","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/service/ServiceSnapshotLoader.java","lineNumber":94,"sourceCode":"        final int schemaId = messageHeaderDecoder.schemaId();\n        if (MessageHeaderDecoder.SCHEMA_ID != schemaId)\n        {\n            throw new ClusterException(\"expected schemaId=\" + MessageHeaderDecoder.SCHEMA_ID + \", actual=\" + schemaId);\n        }\n\n        switch (messageHeaderDecoder.templateId())\n        {\n            case SnapshotMarkerDecoder.TEMPLATE_ID:\n                snapshotMarkerDecoder.wrap(\n                    buffer,\n                    offset + MessageHeaderDecoder.ENCODED_LENGTH,\n                    messageHeaderDecoder.blockLength(),\n                    messageHeaderDecoder.version());\n\n                final long typeId = snapshotMarkerDecoder.typeId();\n                if (SNAPSHOT_TYPE_ID != typeId)\n                {\n                    throw new ClusterException(\"unexpected snapshot type: \" + typeId);\n                }\n\n                switch (snapshotMarkerDecoder.mark())\n                {\n                    case BEGIN:\n                        if (inSnapshot)\n                        {\n                            throw new ClusterException(\"already in snapshot\");\n                        }\n                        inSnapshot = true;\n                        appVersion = snapshotMarkerDecoder.appVersion();\n                        timeUnit = ClusterClock.map(snapshotMarkerDecoder.timeUnit());\n                        return Action.CONTINUE;\n\n                    case END:\n                        if (!inSnapshot)\n                        {\n                            throw new ClusterException(\"missing begin snapshot\");","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/service/ServiceSnapshotLoader.java#L76-L112","documentation":"ServiceSnapshotLoader.onFragment decodes a snapshot replay stream and expects every SnapshotMarker to carry the canonical SNAPSHOT_TYPE_ID. When a marker frame decodes with a different type ID the stream is not an Aeron cluster snapshot the loader understands, so it aborts with a ClusterException rather than misinterpreting the data. This guards against replaying corrupted, truncated, or foreign recordings into cluster services.","triggerScenarios":"Replaying a snapshot recording whose SnapshotMarker decoder yields a typeId != SNAPSHOT_TYPE_ID, e.g. a recording from a different Aeron version or a non-snapshot recording fed to snapshot recovery.","commonSituations":"Pointing cluster recovery at the wrong recording (an old or foreign log/snapshot), snapshot files produced by a different Aeron protocol version, or corrupted recording files whose headers decode as a different type.","solutions":["Recover the cluster using a snapshot taken by a matching Aeron version (check typeId/appVersion of the snapshot)","Regenerate the snapshot from a healthy cluster member via a fresh take-snapshot","Verify the recording ID / archive replay configuration so the correct snapshot recording is loaded","Inspect the recording with aeron archive tooling to confirm the marker frames' type IDs"],"exampleFix":"// before: replaying an old/mismatched recording into recovery\ncontext.clusteredServiceContainer().snapshotStreamChannel(\"aeron:udp?endpoint=old-snap\")...\n// after: use the current cluster's recorded snapshot and matching Aeron version\nClusterTool.takeSnapshot(archive, aeron, consensusModuleProxy, countdownLatch);","handlingStrategy":"validation","validationCode":"// Before replaying, confirm the recording is a current-version cluster snapshot\n// e.g. inspect marker frames with Aeron archive tooling and compare typeId/appVersion\nif (markerTypeId != SNAPSHOT_TYPE_ID) { throw new IllegalArgumentException(\"not a snapshot recording: \" + markerTypeId); }","typeGuard":null,"tryCatchPattern":"try { loader.load(...); } catch (ClusterException e) { abortRecovery(e); }","preventionTips":["Keep all cluster members on the same Aeron version","Only replay recordings explicitly produced by take-snapshot","Verify recording IDs in the cluster recovery plan before replay"],"tags":["aeron-cluster","snapshot","cluster-recovery","protocol-mismatch"],"backgroundTag":"unexpected-response-shape","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"}