{"record":{"id":"2ed1f3417ab49506","repo":"aeron-io/aeron","slug":"expected-schemaid-messageheaderdecoder-schema-id-actual","errorCode":null,"errorMessage":"expected schemaId=\" + MessageHeaderDecoder.SCHEMA_ID + \", actual=\" + schemaId","messagePattern":"expected schemaId=\" \\+ MessageHeaderDecoder\\.SCHEMA_ID \\+ \", actual=\" \\+ schemaId","errorType":"exception","errorClass":"ArchiveException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/ControlSessionAdapter.java","lineNumber":136,"sourceCode":"        return fragmentsRead;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @SuppressWarnings(\"MethodLength\")\n    public void onFragment(final DirectBuffer buffer, final int offset, final int length, final Header header)\n    {\n        ArchiveTracing.traceControlRequest(buffer, offset, length);\n\n        final MessageHeaderDecoder headerDecoder = decoders.header;\n        headerDecoder.wrap(buffer, offset);\n\n        final int schemaId = headerDecoder.schemaId();\n        if (schemaId != MessageHeaderDecoder.SCHEMA_ID)\n        {\n            throw new ArchiveException(\"expected schemaId=\" + MessageHeaderDecoder.SCHEMA_ID + \", actual=\" + schemaId);\n        }\n\n        final Image image = (Image)header.context();\n\n        final int templateId = headerDecoder.templateId();\n        switch (templateId)\n        {\n            case CloseSessionRequestDecoder.TEMPLATE_ID:\n            {\n                final CloseSessionRequestDecoder decoder = decoders.closeSessionRequest;\n                decoder.wrap(\n                    buffer,\n                    offset + MessageHeaderDecoder.ENCODED_LENGTH,\n                    headerDecoder.blockLength(),\n                    headerDecoder.version());\n\n                final long controlSessionId = decoder.controlSessionId();\n                final SessionInfo info = controlSessionByIdMap.get(controlSessionId);","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/ControlSessionAdapter.java#L118-L154","documentation":"ControlSessionAdapter decodes SBE messages from the archive control-response image. Every SBE frame carries a schemaId in its message header; if it does not match the schema id the archive codecs were generated from, the bytes cannot be interpreted, so an ArchiveException is thrown before decoding the templateId.","triggerScenarios":"onFragment receives a buffer whose MessageHeaderDecoder.schemaId() != MessageHeaderDecoder.SCHEMA_ID — e.g. a control response encoded with a different archive protocol version (different aeron-archive version on client vs server) or garbage/foreign protocol bytes arriving on the control channel.","commonSituations":"Client and archive agent running different Aeron versions with incompatible SBE schemas; sending non-archive protocol frames to the control request/response channel; connecting to a proxy/misconfigured endpoint that is not the archive control response stream.","solutions":["Run the same aeron-archive version on both the client and the archive media driver so the SBE schema ids match.","Verify the subscription is bound to the actual archive control response channel/stream, not an unrelated image.","Inspect the first bytes of the incoming fragment to confirm the peer is speaking the Aeron archive SBE protocol.","If integrating a custom peer, regenerate codecs with the same SBE schema (aeron-archive-codecs) used by this build."],"exampleFix":"// before: mixing versions\nimplementation(\"io.aeron:aeron-archive:1.40.0\")\nimplementation(\"io.aeron:aeron-driver:1.44.1\")\n// after: aligned versions\nimplementation(\"io.aeron:aeron-archive:1.44.1\")\nimplementation(\"io.aeron:aeron-driver:1.44.1\")","handlingStrategy":"validation","validationCode":"// client-side: pin aeron-archive versions\nassert io.aeron.archive.ClientContext.class.getPackage()\n    .getImplementationVersion().equals(driverArchiveVersion);","typeGuard":null,"tryCatchPattern":"try { adapter.onFragment(buffer, offset, length, header); }\ncatch (ArchiveException e) {\n    if (e.getMessage().contains(\"expected schemaId\")) {\n        log.error(\"Archive protocol version mismatch; restart with matched versions\", e);\n    }\n}","preventionTips":["Keep client and archive dependencies on the exact same Aeron version.","Subscribe only to genuine archive control response streams.","Add an integration smoke test that connects client and archive before deploying."],"tags":["sbe","protocol-mismatch","archive-client","versioning"],"backgroundTag":"schema-validation-failed","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}