aeron-io/aeron · error · ClusterException

expected schemaId=<MessageHeaderDecoder.SCHEMA_ID>, actual=

Error message

expected schemaId=<MessageHeaderDecoder.SCHEMA_ID>, actual=<schemaId>

What it means

EgressAdapter.onFragment decoded the SBE MessageHeader of an egress fragment and found a schemaId that does not match the cluster egress schema (MessageHeaderDecoder.SCHEMA_ID). It throws ClusterException since decoding with the compiled codecs would be unsafe.

Solutions

  1. Align aeron-cluster versions between client and cluster
  2. Check that the subscription points at the correct egress streamId/channel
  3. Regenerate codecs from the matching schema if customized
  4. Inspect the unexpected schemaId to trace the actual producer of the fragment

Example fix

// before
AeronCluster.connect(new AeronCluster.Context()); // cluster on different schema version
// after
// pin both sides to the same aeron-cluster release before reconnecting
Defensive patterns

Strategy: validation

Validate before calling

MessageHeaderDecoder h = new MessageHeaderDecoder().wrap(buffer, offset);
if (h.schemaId() != MessageHeaderDecoder.SCHEMA_ID) {
    // handle mismatch before calling EgressAdapter.onFragment
}

Try / catch

try {
    adapter.onFragment(buffer, offset, length, header);
} catch (ClusterException ex) {
    // log and skip incompatible fragment
}

Prevention

When it happens

Trigger: Subscribing to a stream carrying a different SBE schema than aeron cluster egress; version mismatch between client and cluster SBE codecs.

Common situations: Mixed Aeron versions after upgrade; wrong subscription channel/stream wiring; custom protocols reusing the egress stream.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/client/EgressAdapter.java:121

        messageHeaderDecoder.wrap(buffer, offset);

        final int templateId = messageHeaderDecoder.templateId();
        final int schemaId = messageHeaderDecoder.schemaId();
        if (schemaId != MessageHeaderDecoder.SCHEMA_ID)
        {
            if (listenerExtension != null)
            {
                listenerExtension.onExtensionMessage(
                    messageHeaderDecoder.blockLength(),
                    templateId,
                    schemaId,
                    messageHeaderDecoder.version(),
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    length - MessageHeaderDecoder.ENCODED_LENGTH);
                return;
            }
            throw new ClusterException("expected schemaId=" +
                MessageHeaderDecoder.SCHEMA_ID + ", actual=" + schemaId);
        }

        switch (templateId)
        {
            case SessionMessageHeaderDecoder.TEMPLATE_ID:
            {
                sessionMessageHeaderDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    messageHeaderDecoder.version());

                final long sessionId = sessionMessageHeaderDecoder.clusterSessionId();
                if (sessionId == clusterSessionId)
                {
                    listener.onMessage(
                        sessionId,

View on GitHub (pinned to 6d60124e15)